/*
 * The MIT License
 *
 * Copyright © 2014 Filip Plesinger, Juraj Jurco.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 * Authors: 
 * 
 * Filip Plesinger <fplesinger@isibrno.cz>
 * Institute of Scientific Instruments of the ASCR, v. v. i.
 * Brno, Czech Republic
 * 
 * Juraj Jurco <xjuraj@isibrno.cz>
 * Institute of Scientific Instruments of the ASCR, v. v. i.
 * Brno, Czech Republic
 */
package cz.academyofscience.upt.challenge2014;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//import org.joda.time.format.DateTimeFormat;
//import org.joda.time.format.DateTimeFormatter;

/**
 *
 * @author xjuraj
 */
public class Channels {

    private static final String TIME_CHANNEL_NAME = "ELAPSED TIME";
//    private static final DateTimeFormatter fmt = DateTimeFormat.forPattern("mm:ss.SSS");
    private Channel timeChannel = null;
    public ArrayList<Channel> data = new ArrayList<>();

    /**
     * Get channel by its name.
     *
     * @param name name of the channel to get
     * @return channel with name specified. When there is no channel with
     * specified name <code>null</code> is returned.
     */
    public Channel getChannelByName(String name) {
        for (Channel channel : data) {
            if (channel.getName().equals(name.toUpperCase())) {
                return channel;
            }
        }
        return null;
    }

    public Channel getFirstEcg() {
        for (Channel ch : data) {
            if (ch.isECG) {
                return ch;
            }
        }
        return null;
    }

    public Channel getFirstBP() {
        for (Channel ch : data) {
            if (ch.isBP) {
                return ch;
            }
        }
        return null;
    }

    public List<Channel> getAllEcgChannels() {
        List<Channel> result = new ArrayList<>();
        for (Channel ch : data) {
            if (ch.isECG) {
                result.add(ch);
            }
        }
        return result;
    }

    public Channel getChannelByPosition(int position) {
        for (Channel channel : data) {
            if (channel.getNumber().equals(position)) {
                return channel;
            }
        }
        return null;
    }

    public void setData(ArrayList<Channel> data) {
        this.data = data;
    }

    public Channels loadChannels(File csvFile) throws IOException {
        Channels result = new Channels();
        FastCSVReader csv = new FastCSVReader(csvFile, 2);
        csv.read();
        //header information
        String[][] header = csv.getHeader();
        double[][] csvData = csv.getDataColumns();

        //all channels, including Time Channel
        for (int i = 0; i < header[0].length; i++) {
            if(i == 0){
                //time channel
                Channel ch = new Channel(header[0][i], i);
                ch.setUnits(header[1][i]);
                ch.setData(csv.getTimeChannel().toArray(new String[0]));
                result.timeChannel = ch;
            } else{
                Channel ch = new Channel(header[0][i], i-1);
                ch.setUnits(header[1][i]);
                ch.values = csvData[i-1];
                result.data.add(ch);
            }
        }
        return result;
    }

    public Channels loadChannels2(File csvFile) throws IOException {
        Channels result = new Channels();
        List<String[]> csv = CSVUtils.loadCSVFile(csvFile, ',', '\'');

//        System.err.println("COMMENT ME!!!");
//        csv = csv.subList(0, 600000);
        if (csv.size() > 2) {
            //header information
            for (int i = 0; i < csv.get(0).length; i++) {
                Channel ch = new Channel(csv.get(0)[i], i);
                result.data.add(ch);
            }
            //units information
            for (int i = 0; i < csv.get(1).length; i++) {
                result.data.get(i).setUnits(csv.get(1)[i]);
            }

            ///////////////// LOAD DATA //////////////////
            List<double[]> dataValues = new ArrayList<>(csv.get(0).length - 1);
            String[] timeData = new String[csv.size() - 2];
            //initialize arrays
            for (int i = 0; i < csv.get(0).length; i++) {
                dataValues.add(new double[csv.size() - 2]);
            }
            //load data
            for (int i = 2; i < csv.size(); i++) {
                String[] line = csv.get(i);
                //first one is time channel
                timeData[i - 2] = line[0];
                //the rest are data
                for (int j = 1; j < line.length; j++) {
                    if (line[j].equals("-")) {
                        line[j] = "0.0";
                    }
                    dataValues.get(j - 1)[i - 2] = Double.parseDouble(line[j]);
                }
            }
            //save data to channels
            for (Channel channel : result.data) {
                if (channel.getName().equals(TIME_CHANNEL_NAME)) {
                    result.timeChannel = channel;
                    result.timeChannel.setData(timeData);
                    result.data.remove(channel);
                    break;
                }
            }
            for (int i = 0; i < result.data.size(); i++) {
                result.data.get(i).values = dataValues.get(i);
                result.data.get(i).setNumber(i);
            }
        }
        return result;
    }

    public Channel getTimeChannel() {
        return timeChannel;
    }

    @Override
    public String toString() {
        if (true) {
            return "Loaded channels";
        }

        String result = "";
        for (Channel channel : data) {
            System.out.print(channel.getName() + "\t");
        }
        System.out.println();
        for (Channel channel : data) {
            System.out.print(channel.getUnits() + "\t");
        }
        System.out.println();
        for (int i = 0; i < data.get(0).values.length; i++) {
            for (Channel channel : data) {
                System.out.print(String.format("%.4f\t", channel.values[i]));
            }
            System.out.println();
        }
        return result;
    }

    public void setEcgFilter(Pattern compile) {
        for (Channel channel : data) {
            channel.setECG_PATTERN(compile);
        }
    }

    public void setBPFilter(Pattern compile) {
        for (Channel channel : data) {
            channel.setBP_PATTERN(compile);
        }
    }

}
