package ctbrec.sites.showup;

import static ctbrec.Model.State.*;
import static ctbrec.io.HttpConstants.*;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;

import javax.xml.bind.JAXBException;

import com.google.common.base.Objects;
import com.iheartradio.m3u8.ParseException;
import com.iheartradio.m3u8.PlaylistException;

import ctbrec.AbstractModel;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.recorder.download.Download;
import ctbrec.recorder.download.HttpHeaderFactory;
import ctbrec.recorder.download.HttpHeaderFactoryImpl;
import ctbrec.recorder.download.StreamSource;

public class ShowupModel extends AbstractModel {

    private String streamId;
    private String streamTranscoderAddr;
    private int[] resolution = new int[2];

    @Override
    public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
        if (ignoreCache) {
            boolean foundInList = false;
            List<Model> modelList = getShowupSite().getModelList();
            for (Model model : modelList) {
                ShowupModel m = (ShowupModel) model;
                if (Objects.equal(m.getName(), getName())) {
                    setOnlineState(m.getOnlineState(false));
                    setStreamId(m.getStreamId());
                    setStreamTranscoderAddr(m.getStreamTranscoderAddr());
                    setDescription(m.getDescription());
                    setPreview(m.getPreview());
                    foundInList = true;
                }
            }
            if (!foundInList) {
                setOnlineState(State.OFFLINE);
            }
        }
        State state = getOnlineState(true);
        return state == ONLINE || state == GROUP || state == PRIVATE;
    }

    @Override
    public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
        StreamSource src = new StreamSource();
        src.width = 480;
        src.height = 360;

        if(streamId == null || streamTranscoderAddr == null) {
            List<Model> modelList = getShowupSite().getModelList();
            for (Model model : modelList) {
                ShowupModel m = (ShowupModel) model;
                if (Objects.equal(m.getName(), getName())) {
                    streamId = m.getStreamId();
                    streamTranscoderAddr = m.getStreamTranscoderAddr();
                }
            }
        }

        int cdnHost = 1 + new Random().nextInt(5);
        int cid = 100_000 + new Random().nextInt(900_000);
        long pid = 10_000_000_000L + new Random().nextInt();
        String urlTemplate = "https://cdn-e0{0}.showup.tv/h5live/http/playlist.m3u8?url=rtmp%3A%2F%2F{1}%3A1935%2Fwebrtc&stream={2}_aac&cid={3}&pid={4}";
        src.mediaPlaylistUrl = MessageFormat.format(urlTemplate, cdnHost, streamTranscoderAddr, streamId, cid, pid);
        List<StreamSource> sources = new ArrayList<>();
        sources.add(src);
        return sources;
    }

    @Override
    public void invalidateCacheEntries() {
        // noop
    }

    @Override
    public void receiveTip(Double tokens) throws IOException {
        // noop
    }

    @Override
    public int[] getStreamResolution(boolean failFast) throws ExecutionException {
        return resolution;
    }

    @Override
    public boolean follow() throws IOException {
        return false;
    }

    @Override
    public boolean unfollow() throws IOException {
        return false;
    }

    private Showup getShowupSite() {
        return (Showup) getSite();
    }

    public String getStreamId() {
        return streamId;
    }

    public void setStreamId(String streamId) {
        this.streamId = streamId;
    }

    public String getStreamTranscoderAddr() {
        return streamTranscoderAddr;
    }

    public void setStreamTranscoderAddr(String streamTranscoderAddr) {
        this.streamTranscoderAddr = streamTranscoderAddr;
    }

    @Override
    public Download createDownload() {
        if (Config.isServerMode() && !Config.getInstance().getSettings().recordSingleFile) {
            return new ShowupDownload(getSite().getHttpClient());
        } else {
            return new ShowupMergedDownload(getSite().getHttpClient());
        }
    }

    @Override
    public HttpHeaderFactory getHttpHeaderFactory() {
        HttpHeaderFactoryImpl fac = new HttpHeaderFactoryImpl();
        Map<String, String> headers = new HashMap<>();
        headers.put(ACCEPT, "*/*");
        headers.put(ACCEPT_LANGUAGE, "pl");
        headers.put(CONNECTION, KEEP_ALIVE);
        if (getSite() != null) {
            headers.put(REFERER, getSite().getBaseUrl());
        }
        headers.put(USER_AGENT, Config.getInstance().getSettings().httpUserAgent);
        fac.setMasterPlaylistHeaders(headers);
        fac.setSegmentPlaylistHeaders(headers);
        fac.setSegmentHeaders(headers);
        return fac;
    }
}
