/*
 * Copyright (C) 2007 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 *
 * This file is part of Spejd.
 *
 * Spejd is free software: it may be distributed and/or modified under 
 * the terms of the GNU General Public License version 3 as published 
 * by the Free Software Foundation and appearing in the file doc/gpl.txt
 * included in the packaging of this file.
 *
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */ 
 
 
package ipipan.spejd.rules;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;


import ipipan.spejd.entities.Entity;
import ipipan.spejd.entities.SentenceBorder;
import ipipan.spejd.readers.Reader;
import ipipan.spejd.readers.ReaderFactory;
import ipipan.spejd.util.Config;
import morfologik.stemmers.Stempelator;

public class Sentence {
    Map<String,Entity> map;
    List<Entity> list;
    
    Reader in;
    PrintStream out;
    String text;
    private LexDictionary dict; // FIXME - czy to na pewno powinno byc tutaj?
    private Config conf = null;
    private Stempelator stemmer;

    // segment numeration stored thread-level:
    public int lastId = 0; // moved here from Entity
    public String getNewId() { // moved here from Entity
        lastId ++;
        return 'a' + Integer.toHexString(lastId);
    }

    
    public Sentence(Config conf, LexDictionary dict, Stempelator stemmer) {
        this.conf = conf;        
        map  = new TreeMap<String,Entity>();
        list = new ArrayList<Entity>();
        this.dict = dict;
        this.stemmer = stemmer;
    }



    public void openFile(File path, Config conf) {

    	if(in != null){
    		in.close();
    		in = null;
    	}

        
        ReaderFactory rf = new ReaderFactory(conf);
        in = rf.getReader(path ,conf, stemmer);
        try {
            File res = new File(path.getParent(), getCoreName(path) + conf.outputSuffix);
            out = new PrintStream(new FileOutputStream(res), true, "utf-8");
        } catch(IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public Entity get(String segId) {
        return map.get(segId);
    }

    void addEntity(Entity e) {
        map.put(e.getId(), e);
        list.add(e);
    }

    public boolean loadSentence() {
        Entity e = null;
        map.clear();
        list.clear();

        if(!in.nextSentence(out)) {
            out.close();
            return false;
        }
        

        addEntity(new SentenceBorder(SentenceBorder.BEGIN, conf));
        while((e = in.loadToken()) != null) {
            if(dict != null)
            dict.apply(e);
            addEntity(e);
        }
        
        addEntity(new SentenceBorder(SentenceBorder.END, conf));

        updateTxt();
        return true;
    }
    
    public Entity[] toArray() {
        //return list.toArray(Entity.ARRAY);
        return list.toArray(new Entity[0]);
    }

    void updateTxt() {
        StringBuilder res = new StringBuilder();
        for(Iterator<Entity> i = list.iterator();
            i.hasNext();
            res.append(i.next().toTxt()));
        text = res.toString();
    }
    
   /**
    * Gets the core of filename (strips extension etc.)
    */
    String getCoreName(File f) {
        String name = f.getName();
        if(name.endsWith(".gz"))
            name = name.substring(0, name.lastIndexOf('.'));
        if(name.indexOf('.') > 0)
            name =  name.substring(0, name.lastIndexOf('.'));
        return name;
    }

    public void update() {
        List<Entity> oldList = list;
        list = new ArrayList<Entity>();
        Entity e;
        for(Iterator<Entity> i = oldList.iterator(); i.hasNext(); ) {
                e = i.next().getReplacement();
            if(e != null)
                addEntity(e);
        }
        updateTxt();
    }

    public void printXML() {
        out.println("<chunk type=\"s\">");
        for(Iterator<Entity> i = list.iterator(); i.hasNext(); )
            i.next().printXML(out);
        out.println("</chunk>");
    }
}

