package ru.yandex.webmaster3.storage.util.yt;

import com.google.common.io.CountingInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import ru.yandex.webmaster3.storage.util.ProgressLogInputStream;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author aherman
 */
class YtReadAndSaveTableCommand extends YtAbstractReadTableCommand<YtReadAndSaveTableCommand.TableCache> {
    private final File saveToFile;

    YtReadAndSaveTableCommand(YtPath path, YtTableRange range, boolean compress, OutputFormat outputFormat, File saveToFile) {
        super(compress, path, range, outputFormat);
        this.saveToFile = saveToFile;
    }

    @Override
    protected YtResult<TableCache> onSuccess(YtStatus status, HttpResponse httpResponse) throws YtCommandException {
        if (status != YtStatus.YT_200_OK) {
            return YtResult.createError(status, "Unable to read table", null);
        }

        HttpEntity entity = httpResponse.getEntity();
        if (entity == null) {
            return YtResult.createResult(status, new TableCache(saveToFile, range, compress, outputFormat, true));
        } else {
            try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(saveToFile))) {
                String streamName = "Cache " + path.getName() + "[" + range.renderInPath().orElse("") + "]";
                IOUtils.copyLarge(
                        new ProgressLogInputStream(new CountingInputStream(entity.getContent()), streamName),
                        bos
                );
                return YtResult.createResult(status, new TableCache(saveToFile, range, compress, outputFormat, false));
            } catch (IOException e) {
                return YtResult.createError(status, "Unable to read table: " + path, e);
            }
        }
    }

    static class TableCache {
        private final File file;
        private final YtTableRange range;
        private final boolean compressed;
        private final OutputFormat outputFormat;
        private final boolean empty;

        TableCache(File file, YtTableRange range, boolean compressed, OutputFormat outputFormat, boolean empty) {
            this.file = file;
            this.range = range;
            this.compressed = compressed;
            this.outputFormat = outputFormat;
            this.empty = empty;
        }

        public File getFile() {
            return file;
        }

        public YtTableRange getRange() {
            return range;
        }

        public boolean isCompressed() {
            return compressed;
        }

        public OutputFormat getOutputFormat() {
            return outputFormat;
        }

        public boolean isEmpty() {
            return empty;
        }
    }
}
