/*
 * The Broad Institute
 * SOFTWARE COPYRIGHT NOTICE AGREEMENT
 * This is copyright (2007-2008) by the Broad Institute/Massachusetts Institute
 * of Technology.  It is licensed to You under the Gnu Public License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *    http://www.opensource.org/licenses/gpl-2.0.php
 *
 * This software is supplied without any warranty or guaranteed support
 * whatsoever. Neither the Broad Institute nor MIT can be responsible for its
 * use, misuse, or functionality.
 */
package org.broad.igv.data.wgs;

//~--- non-JDK imports --------------------------------------------------------
import org.broad.igv.data.Dataset;
import org.broad.igv.feature.Genome;
import org.broad.igv.feature.GenomeManager;
import org.broad.igv.preprocess.NonOverlappingProcessor;
import org.broad.igv.track.TrackType;

//~--- JDK imports ------------------------------------------------------------

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;


import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 *
 * @author jrobinso
 *  
 *  KDR         4       55671614        55671614
 * TNC     9       116837402       116837402
 * PTEN    10      89710798        89710798
 * TP53    17      7517651         7517652
 */
public class SeqDataset implements Dataset {

    String genomeId;
    Genome genome;
    String trackName;

    // int [] locations;
    // float[] data;
    File directory;
    File lociFile;
    String color;
    String[] chromosomes;
    Map<String, List<int[]>> lociMap = new HashMap();

    /**
     * Constructs ...
     *
     *
     * @param path
     */
    public SeqDataset(String path, String fn) {

        directory = new File(path);
        lociFile = new File(fn);

        // if (!(directory.exists() && directory.isDirectory()))
        // {
        // System.err.println("Directory: " + path + " does not exist or is not a directory");
        // }

        readProperties();
        readLoci();
        // scanForChromosomes();

        genome = GenomeManager.getInstance().getGenome(genomeId);

    // locations = new int[250000000];
    // data = new float[locations.length];
    }

    public void setLociFile(File lociFile) {
        this.lociFile = lociFile;
    }

    private void readLoci() {
        if (lociFile != null && lociFile.exists())
        {

            BufferedReader br = null;
            try
            {
                br = new BufferedReader(new FileReader(lociFile));
                String nextLine = null;
                while ((nextLine = br.readLine()) != null)
                {
                    try
                    {
                        String locusString = nextLine.trim();
                        String[] t1 = locusString.split(":");
                        String chr = t1[0];
                        String[] t2 = t1[1].split("-");
                        if (t2.length == 2)
                        {
                            int[] pos = new int[2];
                            pos[0] = Integer.parseInt(t2[0]);
                            pos[1] = Integer.parseInt(t2[1]);
                            List<int[]> posList = lociMap.get(chr);
                            if (posList == null)
                            {
                                posList = new ArrayList();
                                lociMap.put(chr, posList);
                            }
                            posList.add(pos);
                        }

                    } catch (NumberFormatException numberFormatException)
                    {
                        System.out.println("Ignoring locus line: " + nextLine);
                    }

                }
            } catch (IOException ex)
            {
                ex.printStackTrace();
            } finally
            {
                try
                {
                    br.close();
                } catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }

            chromosomes = lociMap.keySet().toArray(new String[]{});
        }


    }

    private void readProperties() {
        File propFile = new File(directory, "property.txt");
        if (propFile.exists())
        {
            InputStream is = null;
            try
            {
                Properties props = new Properties();
                is = new FileInputStream(propFile);
                props.load(is);
                is.close();

                genomeId = props.getProperty("genome");
                trackName = props.getProperty("name");
                color = props.getProperty("color");
            } catch (IOException ex)
            {
                ex.printStackTrace();
            } finally
            {
                try
                {
                    is.close();
                } catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        } else
        {
            genomeId = "hg18";
            trackName = directory.getName();
            color = "0,0,255";
        }
    }

    private void scanForChromosomes() {
        File[] files = directory.listFiles(new FileFilter() {

            public boolean accept(File arg0) {
                return arg0.getName().startsWith("chr") && arg0.getName().endsWith(".bin");
            }
        });
        chromosomes = new String[files.length];
        for (int i = 0; i < files.length; i++)
        {
            chromosomes[i] = files[i].getName().replace(".bin", "").trim();
        }
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public String getName() {
        return trackName;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public TrackType getType() {
        return TrackType.OTHER;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public String getGenome() {
        return genomeId;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public String[] getChromosomes() {
        return chromosomes;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public String getTrackName() {
        return trackName;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public int getWindowSpan() {
        return 1;
    }

    /**
     * Method description
     *
     *
     * @param name
     */
    public void setName(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public String[] getDataHeadings() {
        return new String[]{trackName};
    }

    /*
     * 55671614         55671614
     * TNC     9       116837402       116837402
     * PTEN    10      89710798        89710798
     * TP53    17      7517651         7517652
     */
    /**
     * Method description
     *
     *
     * @param chr
     *
     * @return
     */
    public int[] getStartLocations(String chr) {

        List<int[]> positions = lociMap.get(chr);

        int sz = 0;
        for (int[] pos : positions)
        {
            sz += pos[1] - pos[0];
        }

        int idx = 0;
        int[] locs = new int[sz];
        for (int[] pos : positions)
        {
            for (int i = pos[0]; i < pos[1]; i++)
            {
                locs[idx] = i;
                idx++;
            }
        }

        return locs;
    }

    /**
     * Method description
     *
     *
     * @param chr
     *
     * @return
     */
    public int[] getEndLocations(String chr) {
        return null;
    }

    /**
     * Method description
     *
     *
     * @param chr
     *
     * @return
     */
    public String[] getFeatureNames(String chr) {
        return null;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    public boolean isLogNormalized() {
        return false;
    }

    /**
     * Method description
     *
     *
     * @param heading
     * @param chr
     *
     * @return
     */
    public float[] getData(String heading, String chr) {
        DataInputStream dis = null;
        File inputFile = new File(directory, chr + ".bin");
        if (!inputFile.exists())
        {
            return null;
        }

        List<int[]> positions = lociMap.get(chr);

        int sz = 0;
        for (int[] pos : positions)
        {
            sz += pos[1] - pos[0];
        }

        float[] data = new float[sz];

        int lastPos = 0;

        try
        {
            dis = new DataInputStream(new BufferedInputStream(new FileInputStream(inputFile)));

            for (int[] pos : positions)
            {
                dis.skip((pos[0] - lastPos) * Short.SIZE / 8);
                for (int i = pos[0]; i < pos[1]; i++)
                {
                    if (dis.available() >= (Short.SIZE / 8))
                    {
                        data[i - pos[0]] = (float) dis.readShort();
                    }
                }
                lastPos = pos[1];
            }
            dis.close();
        } catch (IOException e)
        {
            e.printStackTrace();

        } finally
        {
            try
            {
                dis.close();
            } catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }

        return data;
    }

    public String getColorString() {
        return color;
    }

    /*
     * KDR         4       55671614        55671614
     * TNC     9       116837402       116837402
     * PTEN    10      89710798        89710798
     * TP53    17      7517651         7517652
     */
    /**
     * Method description
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        SeqDataset ds = new SeqDataset(args[0], args[1]);

        float[] data = ds.getData("ignored", "chr4");

        NonOverlappingProcessor proc = new NonOverlappingProcessor(ds);
        proc.setZoomMax(7);
        proc.process(args[2]);

        System.out.println(data.length);
    }
}
