
package org.atea.nlptools.macroniser.monogram.model;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import org.atea.nlptools.macroniser.util.Pool;

/**
 * 
 * 
 * 
 * @author University of Waikato - Te Whare Wānanga o Waikato
 * @version 1.0
 * @since   2014-11-20 
 */
public class MonogramModel
{
    private final String DISTINCT_TRANSFORMATIONS_PATH = "distinctTransformations.data";
    private final String INDISTINCT_TRANSFORMATIONS_PATH = "indistinctTransformations.data";
    private final String MONOGRAM_PROBABILITIES_PATH = "monogramProbabilities.data";
    private final String CHARSET_ENCODING = "utf-8";
    private final String DELIMITER = "\t";
    private final String path;
    private Map<String, String> distinctTransformations;
    private Map<String, String[]> indistinctTransformations;
    private Map<String, Double> indistinctProbabilities;
    private Map<String, HashMap<String, Double>> monogramProbabilities;
    private Pool<String> pool;

    /**
     * Create a model with a local pool, the pool is cleared after the model is constructed.
     * @param path File path to data directory
     */
    protected MonogramModel(String path)
    {
        this.path = path;
        this.pool = new Pool<String>();
        init();
        pool.clear();
    }

    /**
     * Create a model with a global pool, the pool must be cleared outside of the class.
     * @param path File path to data directory
     */
    protected MonogramModel(String path, Pool<String> pool)
    {
        this.path = path;
        this.pool = pool;
        init();
    }
    

    /**
     * Initializes the values in a monogram model
     */
    private void init()
    {
        distinctTransformations = new HashMap<String, String>();
        indistinctTransformations = new HashMap<String, String[]>();
        indistinctProbabilities = new HashMap<String, Double>();
        monogramProbabilities = new HashMap<String, HashMap<String, Double>>();

        initDistinctTransformations();
        initIndistinctTransformations();
        initProbabilities();
    }

    /**
     * Gets a Hashmap with the distinct Transformations 
     * @return Hashmap of distinct Transformations eg(aahia -> āhia)
     */
    public Map<String, String> getDistinctTransformations() {
        return distinctTransformations;
    }

    public Map<String, String[]> getIndistinctTransformations() {
        return indistinctTransformations;
    }

    public Map<String, Double> getIndistinctProbabilities() {
        return indistinctProbabilities;
    }

    public Map<String, HashMap<String, Double>> getMonogramProbabilities() {
        return monogramProbabilities;
    }

    public String getDistinctTransformation(String token) {
        return distinctTransformations.get(token);
    }

    public String[] getIndistinctTransformation(String token) {
        return indistinctTransformations.get(token);
    }

    public Double getIndistinctProbability(String token) {
        return indistinctProbabilities.get(token);
    }

    public Double getMonogramProbability(String token, String leftToken) {
        return monogramProbabilities.get(token).get(leftToken);
    }

    public boolean isDistinctTransformation(String token) {
        return distinctTransformations.containsKey(token);
    }

    public boolean isIndistinctTransformation(String token) {
        return indistinctTransformations.containsKey(token);
    }

    public boolean containsIndistinctProbability(String token) {
        return indistinctProbabilities.containsKey(token);
    }

    public boolean containsMonogramProbability(String token, String leftToken)
    {
        if (monogramProbabilities.containsKey(token)) {
            return monogramProbabilities.get(token).containsKey(leftToken);
        }

        return false;
    }

    /**
     * Reads in transformations from given data file
     */
    private void initDistinctTransformations()
    {
        BufferedReader reader = null;
        try
        {
            final String filepath = path + "/" + DISTINCT_TRANSFORMATIONS_PATH;
            reader = new BufferedReader(
                new InputStreamReader(getClass().getResourceAsStream(filepath), CHARSET_ENCODING)
            );
                
            String line;
            while ((line = reader.readLine()) != null)
            {
                final String[] elements = line.split(DELIMITER);
                distinctTransformations.put(pool.getCanonicalObject(elements[0]), pool.getCanonicalObject(elements[1]));
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            close(reader);
        }
    }
    
    /**
     * Reads in indistinct transformations from given data file
     */
    private void initIndistinctTransformations()
    {
        BufferedReader reader = null;
        try
        {
            final String filepath = path + "/" + INDISTINCT_TRANSFORMATIONS_PATH;
            reader = new BufferedReader(
                new InputStreamReader(getClass().getResourceAsStream(filepath), CHARSET_ENCODING)
            );

            String line;
            while ((line = reader.readLine()) != null)
            {
                final String[] elements = line.split(DELIMITER);
                final String[] transformations = new String[elements.length - 1];

                //System.arraycopy(elements, 1, transformations, 0, elements.length - 1); //copy elements 1-n.
                for (int i = 0; i < transformations.length; i++) {
                    transformations[i] = pool.getCanonicalObject(elements[i + 1]);
                }

                indistinctTransformations.put(pool.getCanonicalObject(elements[0]), transformations);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            close(reader);
        }
    }

    /**
     * Reads in probabilities from given data file
     */ 
    private void initProbabilities()
    {
        BufferedReader reader = null;
        try
        {
            final String filepath = path + "/" + MONOGRAM_PROBABILITIES_PATH;
            reader = new BufferedReader(
                new InputStreamReader(getClass().getResourceAsStream(filepath), CHARSET_ENCODING)
            );

            String line;
            while ((line = reader.readLine()) != null)
            {
                final String[] elements = line.split(DELIMITER);
                final String token = elements[0];
                final Double probability = Double.parseDouble(elements[1]);
                indistinctProbabilities.put(token, probability);

                for (int i = 2; i + 1 < elements.length; i += 2)
                {
                    final String nGramToken = elements[i];
                    final Double nGramProbability = Double.parseDouble(elements[i + 1]);

                    if (monogramProbabilities.containsKey(token))
                    {
                        final HashMap<String, Double> map = monogramProbabilities.get(token);
                        map.put(nGramToken, nGramProbability);
                    }
                    else
                    {
                        final HashMap<String, Double> map = new HashMap<String, Double>();
                        map.put(nGramToken, nGramProbability);
                        monogramProbabilities.put(token, map);
                    }
                }
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            close(reader);
        }
    }

    private void close(Reader reader)
    {
        if (reader != null)
        {
            try {
                reader.close();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
