package edu.sc.seis.gee.task;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;

import edu.iris.Fissures.Dimension;
import edu.iris.Fissures.NotImplemented;
import edu.iris.Fissures.Plottable;
import edu.iris.Fissures.IfEvent.EventAccess;
import edu.iris.Fissures.IfNetwork.ChannelId;
import edu.iris.Fissures.IfPlottable.PlottableDC;
import edu.iris.Fissures.IfPlottable.PlottableDCOperations;
import edu.iris.Fissures.IfPlottable.PlottableNotAvailable;
import edu.iris.Fissures.IfPlottable.UnsupportedDimension;
import edu.iris.Fissures.IfSeismogramDC.RequestFilter;
import edu.iris.Fissures.model.MicroSecondDate;
import edu.sc.seis.fissuresUtil.cache.ProxyPlottableDC;
import edu.sc.seis.seisFile.SeisFileException;
import edu.sc.seis.seisFile.fdsnws.AbstractFDSNQuerier;
import edu.sc.seis.seisFile.fdsnws.FDSNWSException;

public class CrocusPlottable extends AbstractFDSNQuerier implements ProxyPlottableDC {

    public CrocusPlottable(CrocusPlottableQueryParams queryParams) {
        this.queryParams = queryParams;
    }

    /** There is no schema for dataselect. Returns null */
    @Override
    public URL getSchemaURL() {
        return null;
    }

    @Override
    public URI formURI() throws URISyntaxException {
        StringBuilder newQuery = new StringBuilder();
        newQuery.append(NETWORK).append("=").append(queryParams.getChannel_id().network_id.network_code).append("&");
        newQuery.append(STATION).append("=").append(queryParams.getChannel_id().station_code).append("&");
        newQuery.append(LOCATION).append("=").append(queryParams.getChannel_id().site_code).append("&");
        newQuery.append(CHANNEL).append("=").append(queryParams.getChannel_id().channel_code).append("&");
        newQuery.append(YEAR).append("=").append(queryParams.getYear()).append("&");
        newQuery.append(DAY).append("=").append(queryParams.getJday()).append("&");
        newQuery.append(MODULO).append("=").append(queryParams.getModulo()).append("&");
        if (newQuery.length() > 1) {
            newQuery.deleteCharAt(newQuery.length() - 1); // zap last &
        }
        return new URI(getScheme(), getUserInfo(), getHost(), getPort(), getPath(), newQuery.toString(), getFragment());
    }
    
    @Override
    public boolean custom_sizes() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Plottable[] get_plottable(RequestFilter request, Dimension pixel_size) throws PlottableNotAvailable,
            UnsupportedDimension, NotImplemented {
        throw new NotImplemented();
    }

    @Override
    public Dimension[] get_whole_day_sizes() {
        return new Dimension[] {new Dimension(6000, 0)};
    }

    @Override
    public Plottable[] get_for_day(ChannelId channel_id, int year, int jday, Dimension pixel_size)
            throws PlottableNotAvailable, UnsupportedDimension {
        return new Plottable[0];
    }
    
    public Plottable[] getPlottable() {
        URI uri = null;
        try {
            int dayBegin = (int)(new MicroSecondDate(queryParams.getYear()+""+queryParams.getJday()+"J00:00:00Z").getTime()/1000);
            connect();
            uri = formURI(); // for errors
            if (!isError()) {
                if (!isEmpty()) {
                    ArrayList<Plottable> outList = new ArrayList<Plottable>();
                    ArrayList<Integer> xList = new ArrayList<Integer>();
                    ArrayList<Integer> yList = new ArrayList<Integer>();
                    DataInputStream dis = new DataInputStream(new BufferedInputStream(getInputStream()));
                    int lastX = -2;
                    try {
                        while (true) {
                            int readX = dis.readInt();
                            int x = (readX-dayBegin)/queryParams.getModulo();
                            if (lastX + 1 != x) {
                                if (xList != null) {
                                    Plottable out = new Plottable();
                                    out.x_coor = new int[xList.size()];
                                    for (int i = 0; i < xList.size(); i++) {
                                        out.x_coor[i] = xList.get(i);
                                    }
                                    out.y_coor = new int[yList.size()];
                                    for (int i = 0; i < yList.size(); i++) {
                                        out.y_coor[i] = yList.get(i);
                                    }
                                    outList.add(out);
                                    xList = new ArrayList<Integer>();
                                    yList = new ArrayList<Integer>();
                                }
                            }
                            int min = dis.readInt();
                            int max = dis.readInt();
                            xList.add(x);
                            yList.add(min);
                            xList.add(x);
                            yList.add(max);
                            lastX = x;
                        }
                    } catch(EOFException e) {
                        if (xList != null) {
                            Plottable out = new Plottable();
                            out.x_coor = new int[xList.size()];
                            for (int i = 0; i < xList.size(); i++) {
                                out.x_coor[i] = xList.get(i);
                            }
                            out.y_coor = new int[yList.size()];
                            for (int i = 0; i < yList.size(); i++) {
                                out.y_coor[i] = yList.get(i);
                            }
                            outList.add(out);
                        }
                    }
                    return outList.toArray(new Plottable[0]);
                } else {
                    // return iterator with nothing in it
                    return new Plottable[0];
                }
            } else {
                throw new RuntimeException("Error: " + getErrorMessage() +"  "+uri);
            }
        } catch(URISyntaxException e) {
            throw new RuntimeException("Error with URL syntax", e);
        } catch(SeisFileException e) {
            if (e instanceof FDSNWSException) {
                ((FDSNWSException)e).setTargetURI(uri);
                throw new RuntimeException(e);
            } else {
                throw new RuntimeException(new FDSNWSException(e.getMessage(), e, uri));
            }
        } catch(IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Dimension[] get_event_sizes() {
        return new Dimension[0];
    }

    @Override
    public Plottable[] get_for_event(EventAccess event, ChannelId channel_id, Dimension pixel_size)
            throws PlottableNotAvailable, UnsupportedDimension {
        throw new PlottableNotAvailable("No implemented");
    }

    @Override
    public PlottableDCOperations getWrappedDC() {
        return null;
    }

    @Override
    public PlottableDCOperations getWrappedDC(Class wrappedClass) {
        return null;
    }

    @Override
    public void reset() {}

    @Override
    public PlottableDC getCorbaObject() {
        return null;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public String getPath() {
        return path;
    }

    public String getScheme() {
        return scheme;
    }

    public String getUserInfo() {
        return userInfo;
    }

    public String getFragment() {
        return fragment;
    }

    String host = "crocus.seis.sc.edu";

    int port = 80;

    String path = "/onesecminmaxb";

    String scheme = "http";

    String userInfo = null;

    String fragment = null;
    
    CrocusPlottableQueryParams queryParams;

    // from CrocusWebConstants
    public static final String NODATA = "nodata";

    public static final String NETWORK_SHORT = "net";

    public static final String NETWORK = "network";

    public static final String STATION_SHORT = "sta";

    public static final String STATION = "station";

    public static final String LOCATION_SHORT = "loc";

    public static final String LOCATION = "location";

    public static final String CHANNEL_SHORT = "cha";

    public static final String CHANNEL = "channel";

    public static final String STARTTIME_SHORT = "start";

    public static final String STARTTIME = "starttime";

    public static final String ENDTIME_SHORT = "end";

    public static final String ENDTIME = "endtime";

    public static final String YEAR = "year";

    public static final String DAY = "day";

    public static final String MODULO = "modulo";
    

    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CrocusPlottable.class);
}
