package ru.yandex.webmaster3.storage.importanturls;

import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

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

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.importanturls.data.ImportantUrlRequest;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.query.Statement;
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;

/**
 * @author Oleg Bazdyrev
 */

@Repository
public class ImportantUrlsYDao extends AbstractYDao {
    private static final DataMapper<ImportantUrlRequest> MAPPER = DataMapper.create(
            F.HOST_ID, F.RELATIVE_URL, F.ADD_DATE, ImportantUrlRequest::new);
    private static final ValueDataMapper<ImportantUrlRequest> VALUE_MAPPER = ValueDataMapper.create2(
            Pair.of(F.HOST_ID, ImportantUrlRequest::getHostId),
            Pair.of(F.RELATIVE_URL, ImportantUrlRequest::getRelativeUrl),
            Pair.of(F.ADD_DATE, ImportantUrlRequest::getAddDate)
    ) ;

    public ImportantUrlsYDao() {
        super(PREFIX_IMPORTANT_URLS, "important_urls");
    }

    /**
     * Добавляет подписки на переданные страницы
     *
     * @param importantUrls
     */
    public void add(Collection<ImportantUrlRequest> importantUrls) {
        batchInsert(VALUE_MAPPER, importantUrls).execute();
    }

    /**
     * Удаляет переданную подписку
     *
     * @param hostId
     * @param relativeUrl
     */
    public void delete(WebmasterHostId hostId, String relativeUrl) {
        delete()
                .where(F.HOST_ID.eq(hostId))
                .and(F.RELATIVE_URL.eq(relativeUrl))
                .execute();
    }

    /**
     * Возвращает все заведенные подписки для указанного хоста и пользователя
     *
     * @param hostId
     * @return
     */
    // если
    public List<ImportantUrlRequest> list(WebmasterHostId hostId) {
        return select(MAPPER)
                .where(F.HOST_ID.eq(hostId))
                .queryForList(Pair.of(F.RELATIVE_URL, ImportantUrlRequest::getRelativeUrl));
    }

    public int count(WebmasterHostId hostId){
        Statement statement = select(F.HOST_ID).countAll().where(F.HOST_ID.eq(hostId)).getStatement();
        return queryOne(statement, DataMapper.SINGLE_COLUMN_INT_MAPPER);
    }

    /**
     * Получает все важные страницы, на которые есть подписка
     *
     * @return
     */
    public void listAll(Consumer<ImportantUrlRequest> consumer) {
        streamReader(MAPPER, consumer);
    }

    /**
     * Хосты НЕ уникальные - каждый хост прилетит столько раз, сколько для него добавлено урлов
     *
     * @param consumer
     */
    public void forEachHost(Consumer<WebmasterHostId> consumer) {
        streamReader(F.HOST_ID, consumer);
    }

    static final class F {
        static final Field<WebmasterHostId> HOST_ID = Fields.hostIdField("host_id");
        static final Field<String> RELATIVE_URL = Fields.stringField("relative_url");
        static final Field<DateTime> ADD_DATE = Fields.jodaDateTimeField("add_date");
    }
}
