package ru.yandex.webmaster3.storage.turbo.dao.autoparser;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.turbo.model.TurboSampleData;
import ru.yandex.webmaster3.core.turbo.model.autoparser.AutoparserToggleState;
import ru.yandex.webmaster3.core.turbo.model.autoparser.TurboAutoparsedHostInfo;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.DataMapper;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.Field;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.Fields;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.ValueDataMapper;

/**
 * Created by ifilippov5 on 18.06.18.
 */
@Repository
public class TurboAutoparsedYDao extends AbstractYDao {

    private static final String TABLE_NAME = "turbo_autoparsed_hosts";

    private static final DataMapper<TurboAutoparsedHostInfo> MAPPER =
            DataMapper.create(F.HOST, F.CHECKBOX_STATE, F.SAMPLES, F.SAMPLES_UPDATE_DATE, F.IMPORTED_FROM_YT, TurboAutoparsedHostInfo::new);

    private static final DataMapper<TurboAutoparsedHostInfo> SHORT_MAPPER =
            DataMapper.create(F.HOST, F.CHECKBOX_STATE, F.SAMPLES_UPDATE_DATE, F.IMPORTED_FROM_YT,
                    (host, cbState, samplesUpdateDate, importFromYT) -> new TurboAutoparsedHostInfo(host, cbState, null, samplesUpdateDate, importFromYT));

    private static final ValueDataMapper<TurboAutoparsedHostInfo> VALUE_DATA_MAPPER = ValueDataMapper.create2(
            Pair.of(F.HOST, TurboAutoparsedHostInfo::getHost),
            Pair.of(F.CHECKBOX_STATE, TurboAutoparsedHostInfo::getCheckboxState),
            Pair.of(F.SAMPLES, TurboAutoparsedHostInfo::getSamples),
            Pair.of(F.SAMPLES_UPDATE_DATE, TurboAutoparsedHostInfo::getUpdateDate),
            Pair.of(F.IMPORTED_FROM_YT, TurboAutoparsedHostInfo::isImportedFromYt)
    );

    public TurboAutoparsedYDao() {
        super(PREFIX_TURBO, TABLE_NAME);
    }

    public void insert(Collection<TurboAutoparsedHostInfo> infos) {
        batchInsert(VALUE_DATA_MAPPER, infos).execute();
    }

    public void update(String host, AutoparserToggleState checkboxState) {
        update(F.CHECKBOX_STATE.set(checkboxState)).where(F.HOST.eq(host)).execute();
    }

    public TurboAutoparsedHostInfo get(String host) {
        return select(MAPPER).where(F.HOST.eq(host)).queryOne();
    }

    public Map<String, TurboAutoparsedHostInfo> get(Collection<String> hosts) {
        if (hosts.isEmpty()) {
            return Collections.emptyMap();
        }
        return select(MAPPER).where(F.HOST.in(hosts)).queryForList().stream()
                .collect(Collectors.toMap(TurboAutoparsedHostInfo::getHost, Function.identity()));
    }

    public TurboAutoparsedHostInfo getShort(String host) {
        return select(SHORT_MAPPER).where(F.HOST.eq(host)).queryOne();
    }

    public void forEach(Consumer<TurboAutoparsedHostInfo> consumer) {
        streamReader(MAPPER, consumer);
    }

    private interface F {
        Field<String> HOST = Fields.stringField("host");
        Field<AutoparserToggleState> CHECKBOX_STATE = Fields.intEnumField("checkbox_state", AutoparserToggleState.R);
        Field<List<TurboSampleData>> SAMPLES = Fields.jsonField2("samples", TurboSampleData.TYPE_REFERENCE);
        Field<DateTime> SAMPLES_UPDATE_DATE = Fields.jodaDateTimeField("samples_update_date");
        Field<Boolean> IMPORTED_FROM_YT = Fields.boolField("imported_from_yt");
    }
}
