/*
 * 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.
*/

/*
 * Dataset.java
 *
 * Created on October 29, 2007, 11:29 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package org.broad.igv.preprocess;

//~--- non-JDK imports --------------------------------------------------------
import org.broad.igv.data.Dataset;
//import org.broad.igv.generic.ObjectCache;

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

import java.io.File;
import java.io.FilenameFilter;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.broad.igv.feature.Genome;
import org.broad.igv.feature.GenomeManager;
//import org.broad.igv.track.TrackProperties;
import org.broad.igv.track.TrackType;

/**
 *      (new SnpBinaryProcessor(name, ds, genomeId, chipFormat, wSpan, norm)).process(outputFile);
 * @author jrobinso
 */
public class SolexaBinaryDataset implements Dataset {

    private String name;

    private TrackType type = TrackType.CHIP;

    private Genome genome;

    private int wSpan = 25;

    private boolean normalized = false;

    /** Temp variable to cache dataCache array for a single chromosome. */

    // ObjectCache<String, float[]> dataCache;
    Map<String, int[]> locations = new HashMap();

    String sourceDirectory;

    FilenameFilter filter;

    BinaryReader reader;

    Map<String, ChromosomeFileGroup> fileGroups = new HashMap();

    Set<String> dataHeadings = new LinkedHashSet();

    Set<String> chromosomes = new HashSet();
    
    //TrackProperties trackProperties = new TrackProperties();

    public SolexaBinaryDataset (
            String name,
            TrackType type,
            String genomeId,
            String sourceDirectory,
            FilenameFilter filter) {
        this.name = name;
        this.type = type;
        //GenomeManager.getInstance().findGenomeAndLoad(genomeId);
        this.genome = GenomeManager.getInstance().getGenome(genomeId);
        if (this.genome == null) {
            throw new RuntimeException("Unknown genome: " + genomeId);
        }
        this.sourceDirectory = sourceDirectory;
        this.filter = filter;
        reader = new BinaryReader();
        reader.setLittleEndian(true);
        initialize();
    }

    public String getName() {
        return name;
    }

    public TrackType getType() {
        return type;
    }

    public String[] getChromosomes() {
        String[] chrs = new String[chromosomes.size()];
        int i = 0;

        for (String chr : chromosomes) {
            chrs[i] = chr;
            i++;
        }

        return chrs;
    }

    // TODO - return Snp ids
    public String[] getFeatureNames(String chr) {
        return null;
    }

    /**
     * Return the dataCache headings (e.g. sample names) for this dataset.
     * @return dataCache headings
     */
    public String[] getDataHeadings() {
        String[] headings = new String[dataHeadings.size()];
        int i = 0;

        for (String h : dataHeadings) {
            headings[i] = h;
            i++;
        }

        return headings;
    }
    // heading+chr -> file
    Map<String, File> dataFileMap = new HashMap();

    // chr -> # data points
    Map<String, Integer> chrDataSize = new HashMap();

    /**
     * Scan the dataCache directory and create ChromosomeFileGroup objects for each
     * chromosome. These objects are later used to load the appropriate dataCache for
     * a chromosome.
     */
    private void initialize() {
        List<File> files = reader.getDataFiles(sourceDirectory, filter);

        for (File file : files) {
            String[] tokens = file.getName().split("\\.");

            // Get the chromosome identifier. String the "chr" prefix (first 3
            // characters).  
            String chr = tokens[0];

            chromosomes.add(chr);

            //String tmp = tokens[1];
            String arrayName = tokens[1];
            int i = 2;
            while (!(tokens[i].equals("bin") || tokens[i].equals("cn"))) {
                arrayName += "." + tokens[i];
                i++;
            }

            String key = arrayName + chr;
            dataFileMap.put(key, file);


            int nFilePts = (int) (file.length() / 4);

            //if(!chrDataSize.containsKey(chr)) {
            //    int nPts = genome.getChromosome(chr).getLength() / 25;
            //    chrDataSize.put(chr, nPts);
            //}
            Integer nDataPoints = chrDataSize.get(chr);
            if (nDataPoints == null) {
                chrDataSize.put(chr, nFilePts);
            } else {
                chrDataSize.put(chr, Math.max(nFilePts, nDataPoints));
            }

            dataHeadings.add(arrayName);
        }

        for (Map.Entry<String, Integer> tmp : chrDataSize.entrySet()) {
            System.out.println("Chr: " + tmp.getKey() + "  Size= " + tmp.getValue());
        }


    }

    public String getGenome() {
        return genome.getName();
    }

    public int[] getStartLocations(String chr) {
        int[] start = locations.get(chr);

        if (start == null) {

            int nPts = chrDataSize.get(chr);
            start = new int[nPts];
            for (int i = 0; i < nPts; i++) {
                start[i] = 25 * i;
            }
            locations.put(chr, start);
        }
        return start;
    }

    public int[] getEndLocations(String chr) {
        return null;
    }

    public float[] getData(String heading, String chr) {
        String key = heading + chr;
        File dataFile = this.dataFileMap.get(key);
        if (dataFile == null) {
            System.out.println("No data file for sample: " + heading +
                    "  chromosome: " + chr);
            return null;
        } else {
            int nPts = this.chrDataSize.get(chr);
            int nFilePts = (int) (dataFile.length() / 4);
            float[] fileData = reader.readFloats(dataFile);

            float[] data = new float[nPts];
            int i = 0;
            while (i < nFilePts) {
                float fd = fileData[i];
                data[i] = (fd < 0 ? Float.NaN : fd);
                i++;
            }
            while (i < data.length) {
                data[i] = Float.NaN;
                i++;
            }


            return data;

        }
    }

    public int getWindowSpan() {
        return wSpan;
    }

    public void setWindowSpan(int wSpan) {
        this.wSpan = wSpan;
    }

    public boolean isLogNormalized() {
        return normalized;
    }

    public void setNormalized(boolean normalized) {
        this.normalized = normalized;
    }

    public boolean isLogValues() {
        // todo - implement
        return false;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getDataMin() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public float getDataMax() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String getColorString() {
        return null;
    }
    
    //    public TrackProperties getTrackProperties() {
    //    return trackProperties;
   // }

}
