package ru.yandex.webmaster3.worker.download.userurls;

import java.io.IOException;
import java.util.Base64;

import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.util.functional.ThrowingConsumer;
import ru.yandex.webmaster3.storage.download.common.MdsExportTaskData;
import ru.yandex.webmaster3.storage.download.common.UserUrlsMdsExportDescriptor;
import ru.yandex.webmaster3.storage.download.common.UserUrlsType;
import ru.yandex.webmaster3.storage.util.yt.AsyncTableReader;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtService;
import ru.yandex.webmaster3.storage.util.yt.YtTableRange;
import ru.yandex.webmaster3.storage.util.yt.YtTableReadDriver;
import ru.yandex.webmaster3.worker.download.AbstractMdsDataProvider;

import static ru.yandex.webmaster3.core.util.functional.ThrowingConsumer.rethrowingUnchecked;

/**
 * @author lester
 */
@AllArgsConstructor(onConstructor_ = {@Autowired})
public class UserUrlsDownloadMdsDataProvider extends AbstractMdsDataProvider<UserUrlsData> {
    private final static byte[] EMPTY_ARCHIVE_GZIP = Base64.getDecoder().decode("H4sICAF9g14AA2VtcHR5LnRzdgADAAAAAAAAAAAA");

    private final YtService ytService;
    private final YtPath indexingYtPath;
    private final YtPath serpClicksYtPath;
    private final YtPath serpShowsYtPath;
    private final YtPath serpAvgPositionYtPath;

    private YtPath getPath(UserUrlsType type) {
        switch (type) {
            case INDEXING:
                return indexingYtPath;
            case SERP_SHOWS:
                return serpShowsYtPath;
            case SERP_CLICKS:
                return serpClicksYtPath;
            case SERP_AVG_POSITION:
                return serpAvgPositionYtPath;
            default:
                throw new IllegalArgumentException("Unsupported type: " + type);
        }
    }

    @Override
    public void provide(MdsExportTaskData exportTaskData, ThrowingConsumer<UserUrlsData, Exception> consumer) throws Exception {
        UserUrlsMdsExportDescriptor descriptor = (UserUrlsMdsExportDescriptor) exportTaskData.getDescriptor();

        ytService.withoutTransaction((cypressService) -> {
            AsyncTableReader<UserUrlsData> reader = new AsyncTableReader<>(
                    cypressService,
                    getPath(descriptor.getUserUrlsType()),
                    YtTableRange.singleKey(descriptor.getHost()),
                    YtTableReadDriver.createYSONDriver(UserUrlsData.class)
            ).withRetry(3).splitInParts(10000L);

            try (AsyncTableReader.TableIterator<UserUrlsData> read = reader.read()) {
                if (!read.hasNext()) {
                    rethrowingUnchecked(consumer).accept(new UserUrlsData("", "", EMPTY_ARCHIVE_GZIP));
                } else {
                    do {
                        rethrowingUnchecked(consumer).accept(read.next());
                    } while (read.hasNext() );
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            return true;
        });
    }

    @Override
    public Class<UserUrlsData> getRowClass() {
        return UserUrlsData.class;
    }
}
