/*
 * 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.entities;

import java.io.PrintStream;
import java.util.regex.Pattern;

import ipipan.spejd.tagset.Pos;
import ipipan.spejd.util.Config;

/**
 * A representation of a single morphosyntactic interpretation: lemma,
 * grammatical class, grammatical categories.  Additionally it
 * contains data for disambiguation annotation - previous
 * disambiguation (for example read from the input file, ignored
 * during parsing, but preserved for the final output) and current
 * disambiguation (added and used by the parser itself).
 */
public class Interpretation implements Comparable<Interpretation> {
    String data;
    boolean disamb, disambSh;
    
    protected Config conf = null;

    public static final String REPLACE_BASE = "%";

    //public static final Interpretation[] array = new Interpretation[0]; // TODO static problems?

    /**
     * Create an interpretation with the specified data. Previous
     * disambiguation is set to false, current to true.
     */
    public Interpretation(String s, Config conf) {
        this.conf = conf;
        data = s;
	    disamb = false;
	    disambSh = true;
    }

    /**
     * Create an interpretation with the specified data and preserving
     * previous disambiguation value. Current disambiguation is set to
     * true.
     */
    public Interpretation(String s, boolean disamb, Config conf) {
        this.conf = conf;
        data = s;
	    this.disamb = disamb;
        disambSh = true;
    }

    /**
     * Create an interpretation by modyfying attributes of an existing
     * one.  Base form (lemma) is copied without modifications.
     */
    public Interpretation(Interpretation interp, String modifier, Config conf) {
        this.conf = conf;
        char[] res = new char[interp.data.length()];
	  for(int i = 0; i < interp.data.length(); i ++) {
	    if(i < modifier.length() && modifier.charAt(i) != '0')
		res[i] = modifier.charAt(i);
	    else 
		res[i] = interp.data.charAt(i);
	  }
	  data = new String(res);
	  disamb = interp.disamb;
	  disambSh = true;
    }

    /**
     * Create an interpretation by modifying attributes of an existing
     * one.  Base form can be substituted or pre/suffixed.
     */
    public Interpretation(Interpretation interp, 
			  String modifier,
			  String base,
              Config conf) {
        this.conf = conf;
	int taglen = conf.tagset.nOfAttributes() - 2;

	// replace attributes overriden by modifier
	// copy the rest
	char[] res = new char[taglen];
	for(int i = 0; i < taglen; i ++) {
		if(i < modifier.length() && modifier.charAt(i) != '0'){
	    	res[i] = modifier.charAt(i);
	    } else 
		res[i] = interp.data.charAt(i);
	}
	
	// check for correctness of attributes and remove illegal modifications
	String pos = conf.tagset.charToValue(conf.tagset.attrToInt(conf.tagset.posAttr),
			res[conf.tagset.attrToInt(conf.tagset.posAttr)-2]);
	String attribs[] = conf.tagset.getPosByName(pos).getAttributes();
	boolean legal[] = new boolean[taglen];
	for(int i=0; i < taglen; i++)
		legal[i] = false;
	legal[0] = true;	
	for(int i=0; i < attribs.length; i++){
		legal[conf.tagset.attrToInt(attribs[i])-2] = true;
	}
	for(int i=0; i < taglen; i++)
		if(!legal[i])
			res[i] = '0';
		
	data = new String(res) + 
	// base from action, replace % with base from interpretation
	// FIXME - sth quicker than replaceAll
	    base.replaceAll(REPLACE_BASE, 
	    		java.util.regex.Matcher.quoteReplacement(
	    				interp.data.substring(taglen)));

	disamb = interp.disamb;
	disambSh = true;      
    }

    public int compareTo(Interpretation i) {
	return data.compareTo(i.data);
    }

    /**
     * Check if the interpretation matches the specified pattern.
     */
    public boolean matches(Pattern pattern) {
	return pattern.matcher(data).matches();
    }

    /**
     * Mark the interpretations as deleted (set the disambiguation
     * annotation).
     */
    public void delete() {
	disambSh = false;
    }

    /**
     * Modify attributes of an interpretations.  
     */ 
    public void modify(String modifier) {
	char[] res = new char[data.length()];
	for(int i = 0; i < data.length(); i ++) {
	    if(i < modifier.length() && modifier.charAt(i) != '0')
		res[i] = modifier.charAt(i);
	    else 
		res[i] = data.charAt(i);
	}
	data = new String(res);
    }

    public String getBase() {
	return data.substring(conf.tagset.nOfAttributes()-2);
    }


    public void printTxt(StringBuilder res) {
	if(disambSh) {
	    res.append('<');
	    res.append(data);
	}
    }

    public void printXML(PrintStream out) {
        
	int baseIndex = conf.tagset.nOfAttributes() - 2;
	if(conf.discardDeleted && !disambSh)
	    return;
	out.print("<lex");
	if(disamb) 
	    out.print(" disamb=\"1\"");
	if(!disambSh)
	    out.print(" disamb_sh=\"0\"");
	out.print("><base>");
	out.print(data.substring(baseIndex));
	out.print("</base><ctag>");
	out.print(conf.tagset.fToCtag(data.substring(0, baseIndex)));
	out.println("</ctag></lex>");  
    }
}
