package foundation.stack.datamill.cucumber;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import foundation.stack.datamill.db.DatabaseClient;
import foundation.stack.datamill.db.Row;
import org.json.JSONObject;
import rx.Observable;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

/**
 * @author Ravi Chodavarapu (rchodava@gmail.com)
 */
public class DatabaseSteps {

    private final static String SQL_SELECT = "SELECT * FROM ";
    private final static String SQL_WHERE = " WHERE ";
    private final static String SQL_AND = " AND ";

    private final PlaceholderResolver placeholderResolver;

    public DatabaseSteps(PlaceholderResolver placeholderResolver) {
        this.placeholderResolver = placeholderResolver;
    }

    @Given("^the (.+) table in (.+) contains a row with:$")
    public void storeDatabaseRow(String tableName, String databaseUrl, String json) {
        String resolvedUrl = placeholderResolver.resolve(databaseUrl);
        String resolvedJson = placeholderResolver.resolve(json);

        JSONObject rowJson = new JSONObject(resolvedJson);

        int count = new DatabaseClient(resolvedUrl).insertInto(tableName).row(builder -> {
            for (String propertyName : rowJson.keySet()) {
                Object value = rowJson.get(propertyName);
                if (value != null) {
                    if (value == JSONObject.NULL) {
                        builder.put(propertyName, null);
                    } else if (value instanceof Number || value instanceof String) {
                        builder.put(propertyName, value);
                    }
                }
            }

            return builder.build();
        }).count().toBlocking().last();

        assertEquals("Failed to insert row into " + tableName, 1, count);
    }

    @Then("^the (.+) table in (.+) should have (.+) where (.+)$")
    public void checkDatabaseRowExists(String tableName, String databaseUrl, String criteriaFragment, String testFragment) {
        String resolvedUrl = placeholderResolver.resolve(databaseUrl);
        String resolvedCriteriaFragment = placeholderResolver.resolve(criteriaFragment);
        String resolvedTestFragment = placeholderResolver.resolve(testFragment);
        Row row = executeSelect(resolvedUrl, buildQuery(tableName, resolvedCriteriaFragment, resolvedTestFragment)).toBlocking().lastOrDefault(null);
        assertThat(row, notNullValue());
    }

    @Then("^the (.+) table in (.+) should contain a row where (.+)$")
    public void checkDatabaseRowExists(String tableName, String databaseUrl, String testFragment) {
        String resolvedUrl = placeholderResolver.resolve(databaseUrl);
        String resolvedTestFragment = placeholderResolver.resolve(testFragment);
        Row row = executeSelect(resolvedUrl, buildQuery(tableName, resolvedTestFragment, null)).toBlocking().lastOrDefault(null);
        assertThat(row, notNullValue());
    }

    private Observable<Row> executeSelect(String resolvedUrl, String sql, Object... parameters) {
        return new DatabaseClient(resolvedUrl).query(sql, parameters).stream();
    }

    protected String buildQuery(String tableName, String testFragment, String criteriaFragment) {
        StringBuilder queryBuilder = new StringBuilder(SQL_SELECT);

        queryBuilder.append(tableName);
        queryBuilder.append(SQL_WHERE);
        queryBuilder.append(testFragment);

        if (criteriaFragment != null && !criteriaFragment.isEmpty()) {
            queryBuilder.append(SQL_AND);
            queryBuilder.append(criteriaFragment);
        }
        return queryBuilder.toString();
    }

}

@@ -869,39 +869,99 @@
 n(%22%5E
-the (.+) table in
+%22 + Phrases.SUBJECT + %22 store%22 + Phrases.OPTIONAL_PLURAL + %22 in table
  (.+) 
-c
 on
-tains
+ database (.+)
  a r
@@ -1548,16 +1548,40 @@
 ect.NULL
+ %7C%7C value.equals(%22null%22)
 ) %7B%0A    
@@ -1654,16 +1654,36 @@
        %7D
+%0A                   
  else if
@@ -3252,20 +3252,21 @@
  return 
-new 
+build
 Database
@@ -3321,24 +3321,148 @@
 m();%0A    %7D%0A%0A
+    private DatabaseClient buildDatabaseClient(String resolvedUrl) %7B%0A        return new DatabaseClient(resolvedUrl);%0A    %7D%0A%0A
     protecte

Allow inserts from feature file.