package example;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.freedomoss.crowdcontrol.webharvest.plugin.datastore.enums.DataStoreColumnType;
import org.webharvest.runtime.processors.plugins.DbRowVariable;

import com.workfusion.rpa.core.plugin.PluginAdapterFactory;
import com.workfusion.rpa.core.plugin.datastore.DatastorePluginAdapter;

import static com.workfusion.rpa.core.plugin.PluginAdapterFactory.PluginsEnum.DATA_STORE;

public class DatastoreTransactionalExample  {

    private final DatastorePluginAdapter datastorePluginAdapter = PluginAdapterFactory.getInstance().getPluginAdapter(DATA_STORE);
    private static final String DS_NAME = "awesome_db_name_transactional_examplle";
    private static final String TEXT_COLUNM_NAME = "textcolumn";
    private static final String DATE_COLUNM_NAME = "datecolumn";
    private static final String INT_COLUNM_NAME = "intcol";
    private static final String TIMESTAMP_COLUNM_NAME = "timestampcol";
    private static final String DATE = "2006-11-11";
    private static final String TIMESTAMP = "2016-06-22 19:10:25";



    public void createDatastore() {
        final Map<String, DataStoreColumnType> s = new HashMap();
        s.put(TEXT_COLUNM_NAME, DataStoreColumnType.TEXT);
        s.put(DATE_COLUNM_NAME, DataStoreColumnType.DATE);
        s.put(INT_COLUNM_NAME, DataStoreColumnType.INTEGER);
        s.put(TIMESTAMP_COLUNM_NAME, DataStoreColumnType.TIMESTAMP);

        datastorePluginAdapter.createDatastore(DS_NAME, s, null);
    }

    public void delete() {
        String deleteQuery = "delete FROM @this WHERE (@id % 2 = 0)  and textcolumn = 'row to be deleted inside transaction';";
        datastorePluginAdapter.beginTransaction();
        datastorePluginAdapter.deleteQuery(DS_NAME, deleteQuery);
        datastorePluginAdapter.commitTransaction();
    }

    public void update() {
        String updateQuery = "update @this set timestampcol = CURRENT_TIMESTAMP where textcolumn = 'row to be updated inside transaction' and textcolumn != '''\"<>&'";
        datastorePluginAdapter.beginTransaction();

        datastorePluginAdapter.updateQuery(DS_NAME, updateQuery);

        datastorePluginAdapter.commitTransaction();

    }

    public List<DbRowVariable> select() {
        datastorePluginAdapter.beginTransaction();

        String query1 = "select * from @this where textcolumn != '''\"<>&' ";
        final List<DbRowVariable> dbRowVariables = datastorePluginAdapter.selectQuery(DS_NAME, query1);

        datastorePluginAdapter.commitTransaction();

        return dbRowVariables;
    }


    public void insertRow() {
        datastorePluginAdapter.beginTransaction();

        final Map<String, String> row = new HashMap<>();
        row.put(TEXT_COLUNM_NAME, "b1&<>\"''_single row insert");
        //  row.put(DATE_COLUNM_NAME, DATE);
        // row.put(INT_COLUNM_NAME, Integer.MAX_VALUE + "");//Long is not supported here
        // row.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        datastorePluginAdapter.insertRow(DS_NAME, row);

        datastorePluginAdapter.commitTransaction();
    }

    public void insertRowsListOfRows() {
        datastorePluginAdapter.beginTransaction();

        final Map<String, String> row = new HashMap<>();
        row.put(TEXT_COLUNM_NAME, "multipleinsertRowsAsMap");
        row.put(DATE_COLUNM_NAME, DATE);
        row.put(INT_COLUNM_NAME, "8888999");
        row.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        final List<Map<String, String>> objects = new ArrayList<>();

        objects.add(row);
        objects.add(row);
        objects.add(row);

        datastorePluginAdapter.insertRowsAsMap(DS_NAME, objects);

        datastorePluginAdapter.commitTransaction();

    }

    public void insertRowsListOfLists() {
        datastorePluginAdapter.beginTransaction();
        final List<List<String>> objects = new ArrayList<>();
        final String rowToBeDeleted = "row to be deleted inside transaction";
        objects.add(Arrays.asList(TEXT_COLUNM_NAME, DATE_COLUNM_NAME, INT_COLUNM_NAME, TIMESTAMP_COLUNM_NAME));
        objects.add(Arrays.asList("multipleinsertRowsAsList", DATE, "1111", TIMESTAMP));
        objects.add(Arrays.asList("multipleinsertRowsAsList", DATE, "2222", TIMESTAMP));
        objects.add(Arrays.asList("row to be updated inside transaction", DATE, "3333", TIMESTAMP));
        objects.add(Arrays.asList("row to be updated inside transaction", DATE, "4444", TIMESTAMP));
        objects.add(Arrays.asList(rowToBeDeleted, DATE, "5555", TIMESTAMP));
        objects.add(Arrays.asList(rowToBeDeleted, DATE, "6666", TIMESTAMP));
        objects.add(Arrays.asList(rowToBeDeleted, DATE, "7777", TIMESTAMP));
        objects.add(Arrays.asList(rowToBeDeleted, DATE, "8888", TIMESTAMP));

        datastorePluginAdapter.insertRowsAsList(DS_NAME, objects);
        datastorePluginAdapter.commitTransaction();

    }


    public void exceptionalExecution() {
        datastorePluginAdapter.beginTransaction();
        try {
            datastorePluginAdapter.selectQuery("name that does not exist", "select * from @this");
        } catch (Exception e) {
            final StringWriter sw = new StringWriter();
            final PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            final String sStackTrace = "Planned exception with transaction: " + sw.toString();

            final Map<String, String> row = new HashMap<>();
            row.put(TEXT_COLUNM_NAME,  (sStackTrace.replaceAll("'", "''")));
            final DatastorePluginAdapter datastorePluginAdapter2 = PluginAdapterFactory.getInstance().getPluginAdapter(DATA_STORE);
            datastorePluginAdapter2.beginTransaction();
            datastorePluginAdapter2.insertRow(DS_NAME, row);
            datastorePluginAdapter2.commitTransaction();
        }
        datastorePluginAdapter.commitTransaction();
    }

    public void transactionCommited() {

        datastorePluginAdapter.beginTransaction();

        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP,  textcolumn = 'updated Transactionally' where  textcolumn != '''\"<>&' and intcol = '1111'");
        final Map<String, String> row = new HashMap<>();
        row.put(TEXT_COLUNM_NAME, "transactional0");
        row.put(DATE_COLUNM_NAME, DATE);
        row.put(INT_COLUNM_NAME, "1067656646");
        row.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        final List<Map<String, String>> objects = new ArrayList<>();

        objects.add(row);
        objects.add(row);
        objects.add(row);

        datastorePluginAdapter.insertRowsAsMap(DS_NAME, objects);


        final Map<String, String> row1 = new HashMap<>();
        row1.put(TEXT_COLUNM_NAME, "to be updated in transaction");
        row1.put(DATE_COLUNM_NAME, DATE);
        row1.put(INT_COLUNM_NAME, "6666668");
        row1.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        final List<Map<String, String>> objects1 = new ArrayList<>();

        objects1.add(row1);
        objects1.add(row1);
        objects1.add(row1);

        datastorePluginAdapter.insertRowsAsMap(DS_NAME, objects1);

        datastorePluginAdapter.commitTransaction();


        datastorePluginAdapter.beginTransaction();

        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP,  textcolumn = 'updated Transactionally' where  textcolumn != '''\"<>&' and textcolumn = 'transactional.'");

        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP,  textcolumn = 'updated Transactionally' where  textcolumn = 'to be updated in transaction' ");

        datastorePluginAdapter.commitTransaction();

    }


    public void transactionUncommited() {

        datastorePluginAdapter.beginTransaction();


        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP, textcolumn = 'updated Transactionally' where  textcolumn != '''\"<>&' and intcol = '1111'");
        final Map<String, String> row = new HashMap<>();
        row.put(TEXT_COLUNM_NAME, "transactional0 will not be commited");
        row.put(DATE_COLUNM_NAME, DATE);
        row.put(INT_COLUNM_NAME, "6666866");
        row.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        final List<Map<String, String>> objects = new ArrayList<>();

        objects.add(row);
        objects.add(row);
        objects.add(row);

        datastorePluginAdapter.insertRowsAsMap(DS_NAME, objects);

        final Map<String, String> row1 = new HashMap<>();
        row1.put(TEXT_COLUNM_NAME, "to be updated in transaction will not be commited");
        row1.put(DATE_COLUNM_NAME, DATE);
        row1.put(INT_COLUNM_NAME, "1663666296");
        row1.put(TIMESTAMP_COLUNM_NAME, TIMESTAMP);

        final List<Map<String, String>> objects1 = new ArrayList<>();

        objects1.add(row1);
        objects1.add(row1);
        objects1.add(row1);

        datastorePluginAdapter.insertRowsAsMap(DS_NAME, objects1);

        datastorePluginAdapter.selectQuery(DS_NAME, "select * from @this where textcolumn = 'transactional. will not be commited'");
        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP,  textcolumn = 'updated Transactionally will not be commieted' where  textcolumn != '''\"<>&' and textcolumn = 'transactional. will not be commited'");

        datastorePluginAdapter.updateQuery(DS_NAME, "update @this set timestampcol = CURRENT_TIMESTAMP,  textcolumn = 'will not be updated Transactionally' where  textcolumn = 'to be updated in inner transaction will not be commited' ");
    }


}
