/*
 * Copyright (c) 2007-2010 by The Broad Institute, Inc. and the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * This software is licensed under the terms of the GNU Lesser General Public License (LGPL), Version 2.1 which
 * is available at http://www.opensource.org/licenses/lgpl-2.1.php.
 *
 * THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR WARRANTIES OF
 * ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT
 * OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE.  IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR
 * RESPECTIVE TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES OF
 * ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES, ECONOMIC
 * DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER THE BROAD OR MIT SHALL
 * BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE
 * FOREGOING.
 */

package org.broad.igv.tools.parsers;

import org.apache.log4j.Logger;
import org.broad.igv.feature.Locus;

import java.io.*;
import java.util.List;


/**
 * @author jrobinso
 * @date Oct 9, 2010
 */
public class GCTtoIGVConverter {

    private static Logger log = Logger.getLogger(GCTtoIGVConverter.class);


    /**
     * Parse the file and output in ".igv" format
     *
     * @return
     */
    public static void convert(File inputFile, File outputFile, String probeResource, String genome) throws IOException {

        GeneToLocusHelper locusHelper = new GeneToLocusHelper(probeResource, genome);


        BufferedReader reader = null;
        PrintWriter writer = null;

        try {
            reader = new BufferedReader(new FileReader(inputFile));
            writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));

            // Assume gene expression for now.
            writer.println("#type=GENE_EXPRESSION");

            // Skip first 2 rows
            reader.readLine();
            reader.readLine();

            // Parse the header line
            String headerLine = reader.readLine();
            String[] tokens = headerLine.split("\t");

            //The sample names in a GCT file start at column 2
            writer.print("Chr\tStart\tEnd\tProbe");
            for (int i = 2; i < tokens.length; i++) {
                writer.print("\t" + tokens[i]);
            }
            writer.println();

            String nextLine = null;
            while ((nextLine = reader.readLine()) != null) {

                // A gct row can map to multiple loci, normally this indicates a problem with the probe
                DataRow row = new DataRow(nextLine);
                String probe = row.getProbe();
                List<Locus> loci = locusHelper.getLoci(probe, row.getDescription());
                if (loci == null || loci.isEmpty()) {
                    System.out.println("No locus found for: " + probe + "  " + row.getDescription());
                } else {
                    for (Locus locus : loci) {
                        writer.print(locus.getChr() + "\t" + locus.getStart() + "\t" + locus.getEnd() + "\t" + probe );
                        writer.println(row.getData());
                    }
                }

            }
        }
        finally {
            if (reader != null) {
                reader.close();
            }
            if (writer != null) {
                writer.close();
            }
        }

    }

    /**
     * Represents a row of data from a GCT file.  Using this class if more effecient than tokeninzing the entire line.
     * Some GCT files have over a thousand columns and we're only interested in the first 2
     */
    static class DataRow {
        private String probe;
        private String description;
        private String data;

        DataRow(String string) {
            int firstTab = string.indexOf('\t');
            int secondTab = string.indexOf('\t', firstTab + 1);

            // TODO -- if either of the indeces firstTab or secondTab are < 0 throw an exception
            probe = string.substring(0, firstTab);
            description = string.substring(firstTab, secondTab);
            data = string.substring(secondTab);
        }

        private String getProbe() {
            return probe;
        }

        public String getDescription() {
            return description;
        }

        public String getData() {
            return data;
        }
    }
}