package fmph.io;

import calhoun.analysis.crf.io.InputSequence;
import calhoun.analysis.crf.io.InputSequenceInt;
import calhoun.analysis.crf.io.InterleavedInputComponentBase;

import calhoun.util.Assert;
import calhoun.util.ErrorException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;

import java.util.Map;

/** reads in an input consisting of a list of ints that correspond to binary values.  Can be used as a standalone
 * input component or part of an interleaved input. Empty lines and lines beginning with '>' are ignored.
 */
public class IntWithHeaderInput extends InterleavedInputComponentBase {
    public static final String HEADER_START = ">";

    public boolean read(BufferedReader r, Map<String, InputSequence<?>> output) throws IOException {
        int[] data = readSequence(r);
        if (data == null) {
            return false;
        }
        output.put(getName(), new InputSequenceInt(data));
        return true;
    }

    public int[] readSequence(BufferedReader r) throws IOException {
        String str = null;
        while (true) {
            str = r.readLine();
            if(str == null) return null;
            if(str.equals("") || str.startsWith(HEADER_START)) {
                continue;
            } else {
                break;
            }
        }
        
        
        int[] data = new int[str.length()];
        try {
            for (int i = 0; i < str.length(); ++i) {
                int temp = str.charAt(i) - '0';
                if ((temp < 0) || (temp > 9)) {
                    temp = str.charAt(i) - 'A' + 10;

                    if ((temp < 10) || (temp > 35)) {
                        temp = str.charAt(i) - 'a' + 36;
                        Assert.a((temp >= 36) && (temp < 62), "Offending character was '" + str.charAt(i));
                    }
                }
                data[i] = temp;
            }
        } catch (NumberFormatException ex) {
            throw new ErrorException(ex);
        }
        return data;
    }

    public void write(Writer w, Map<String, ? extends InputSequence<?>> data) throws IOException {
        writeSequence(w, ((InputSequenceInt)data.get(getName())).getData());
    }

    public void writeSequence(Writer w, int[] data) throws IOException {
        for (int i : data) {
            if (i < 10) {
                w.write('0' + i);
            } else if (i < 36) {
                w.write('A' + (i - 10));
            } else if (i < 62) {
                w.write('a' + (i - 36));
            } else {
                throw new IOException();
            }
        }
        w.write('\n');
    }

}
