package ru.yandex.webmaster3.validator.common;

import java.io.*;
import java.net.URL;
import java.util.Objects;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipInputStream;

import com.ning.http.client.HttpResponseBodyPart;
import com.ning.http.client.HttpResponseHeaders;
import org.apache.commons.io.input.BOMInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author leonidrom
 */
public class Pipe implements Closeable {
    private static final Logger log = LoggerFactory.getLogger(Pipe.class);

    private final URL url;
    private final HttpResponseHeaders headers;
    private final PipedOutputStream pipeOut;
    private final PipedInputStream pipeIn;

    Pipe(URL url, HttpResponseHeaders headers) throws IOException {
        this.url = url;
        this.headers = headers;
        this.pipeIn = new PipedInputStream();
        this.pipeOut = new PipedOutputStream(pipeIn);
    }

    void write(byte[] data) throws IOException {
        pipeOut.write(data);
    }
    
    InputStream getInputStream() throws IOException {
        Pipe.StreamFormat format = detectInputStreamFormat();
        switch (format) {
            case Gz: {
                return new BOMInputStream(new GZIPInputStream(pipeIn));
            }

            case Zip: {
                ZipInputStream zipInputStream = new ZipInputStream(pipeIn);
                zipInputStream.getNextEntry();
                return new BOMInputStream(zipInputStream);
            }

            default: {
                return new BOMInputStream(pipeIn);
            }
        }        
    }

    private StreamFormat detectInputStreamFormat() {
        String compression = headers.getHeaders().getFirstValue("Content-Encoding");
        String urlAsString = url.toString();

        if (urlAsString.endsWith(".gz")) {
            return StreamFormat.Gz;
        } else if (urlAsString.endsWith(".zip")) {
            return StreamFormat.Zip;
        } else if (Objects.equals("gzip", compression) || Objects.equals("gz", compression) || Objects.equals("x-gzip", compression)) {
            return StreamFormat.Gz;
        } else if (Objects.equals("zip", compression)) {
            return StreamFormat.Zip;
        }

        return StreamFormat.NoCompression;
    }

    @Override
    public void close() throws IOException {
        pipeOut.close();
    }

    private enum StreamFormat {
        NoCompression,
        Gz,
        Zip,
        ;
    }
}
