package ru.yandex.webmaster3.storage.util.ydb.querybuilder;

/*
 * @author kravchenko99
 * @date 8/24/20
 */

import java.util.*;

import com.yandex.ydb.table.values.Value;

import ru.yandex.webmaster3.storage.util.ydb.ExecuteQuery;
import ru.yandex.webmaster3.storage.util.ydb.query.DbFieldInsertAssignment;
import ru.yandex.webmaster3.storage.util.ydb.query.Statement;

public abstract class AbstractInsert extends Statement {
    Collection<DbFieldInsertAssignment> list;
    private ExecuteQuery executeQuery;

    public AbstractInsert(String tablePrefix, String table, OperationType type, Collection<DbFieldInsertAssignment> list, ExecuteQuery executeQuery) {
        super(tablePrefix, table, type);
        this.list = list;
        this.executeQuery = executeQuery;

        initIndex();
    }

    private void initIndex() {
        int index = 0;
        for (DbFieldInsertAssignment a : list) {
            index = a.initIndex(index);
        }
    }


    public AbstractInsert withValue(DbFieldInsertAssignment value) {
        list = new ArrayList<>(list);
        list.add(value);

        initIndex();

        return this;
    }

    @Override
    public String toQueryString() {
        StringBuilder sb = new StringBuilder(TABLE_PREFIX).append("'").append(tablePrefix).append("';\n");
        Set<Integer> set = new HashSet<>();
        for (var a : list) {
            a.appendDeclaration(sb, set);
        }
        sb.append(operationType.name()).append(" INTO ").append(table).append("(");
        for (var a : list) {
            a.appendName(sb);
            sb.append(",");
        }
        sb.setLength(sb.length() - 1);
        sb.append(")\nVALUES(");
        for (var a : list) {
            a.appendParametr(sb);
            sb.append(",");
        }
        ;
        sb.setLength(sb.length() - 1);
        sb.append(");");
        return sb.toString();
    }

    @Override
    public Map<String, Value> getParameters() {
        Map<String, Value> result = new HashMap<>();
        list.forEach(e -> e.putParameter(result));
        return result;
    }

    public void execute() {
        this.executeQuery.execute(this);
    }

}
