/*
 * Copyright (C) 2009 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 WSDDE.
 *
 * WSDDE 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 wsdde;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Vector;

import weka.classifiers.Classifier;
import weka.core.FastVector;
import weka.core.Instances;
import weka.filters.Filter;
import wsdde.corpus.KWIC;

import wsdde.corpus.WSDCorpus;
import wsdde.generator.FeatureGenerator;


/**
 *  
 * 
 * @author "Rafal Mlodzki"
 *
 */

public class WSDModel implements Serializable {

	private static final long serialVersionUID = 4329550140737387953L;

	
	//private int trainingSetSize;
	
	HashMap<String,FeatureGenerator> whichGenerator;
	Counter selectedFeatures;
	FastVector senses;
	Vector<FeatureGenerator> fgs;
	
	Classifier classifier;
	
	
	
	
	public void saveModel(String filename) {
		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try	{
		       fos = new FileOutputStream(filename);
		       out = new ObjectOutputStream(fos);
		       out.writeObject(this);
		       out.close();
		}
		catch(IOException ex) {
		       ex.printStackTrace();
		}	
	}
	
	
	public static WSDModel loadModel(String filename) {
		WSDModel wsdmodel= null;
		   FileInputStream fis = null;
		   ObjectInputStream in = null;
		   try
		   {
		     fis = new FileInputStream(filename);
		     in = new ObjectInputStream(fis);
		     wsdmodel = (WSDModel)in.readObject();
		     in.close();
		   }
		   catch(IOException ex)
		   {
		     ex.printStackTrace();
		   }
		   catch(ClassNotFoundException ex)
		   {
		     ex.printStackTrace();
		   }
		   return wsdmodel;
	}
	
	
	public WSDModel(WSDCorpus trainingSet,final WSDMethod settings) {
		
		//extract features, prepare feature vectors
		fgs = new Vector<FeatureGenerator>();
		for (FeatureGenerator featureGenerator : settings) {
			fgs.add(featureGenerator);
		}
		trainingSet.generateFeatures(fgs);
		trainingSet.computeMainCounter(); //podlicz glowny licznik (suma wszystkich wygenerowanych cech (zliczone wystapienia kontekstow dla kazdej, dla IDF)
		trainingSet.sensesFromKWICS();
		Instances data = trainingSet.toWeka();
		
		
		
		//filter features
		
		if (settings.filter!=null) {
			try {
				settings.filter.setInputFormat(data);
				data = Filter.useFilter(data, settings.filter);   // apply filter
			} catch (Exception e) {
				//System.out.println("kukuj");
				//e.printStackTrace();
			}
			data.setClassIndex(data.numAttributes() - 1);//setting class attribute
			selectedFeatures= new Counter();
			for (int i=0; i<data.numAttributes()-1; i++) {
				selectedFeatures.put(data.attribute(i).name(), trainingSet.counter.get(data.attribute(i).name()));
			}			
		}
		whichGenerator = trainingSet.whichGenerator;
		senses = trainingSet.senses;
		
		//wsdde.general.Utils.saveInFile(data.toString(), "train_selected.arff");
		
		trainingSet.clear();
		//build classifier
		classifier = settings.classifier;
	//	System.out.println("building");
		try {
			classifier.buildClassifier(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		
	}

	//public void evaluate() {}
	
	
	public void classify(WSDCorpus testSet, EvaluationResult results, boolean save) {
		
		testSet.generateFeatures(fgs);
		testSet.whichGenerator = this.whichGenerator;
		testSet.setSenses(this.senses);// = trainingSet.senses;
		testSet.setMainCounter(this.selectedFeatures);
		Instances testData = testSet.toWeka();
		testData.setClassIndex(testData.numAttributes() - 1);
		//wsdde.general.Utils.saveInFile(testData.toString(), "test.arff");
		
		int correct=0;
		
		for (int j = 0; j < testData.numInstances(); j++) {
			try {
				//System.out.print(testSet.senses.elementAt((int)classifier.classifyInstance(testData.instance(j)))+" ");
				//System.out.println(testSet.get(j).toHumanString());
			//	double [] ds =classifier.distributionForInstance(testData.instance(j));
			//	double d = classifier.classifyInstance(testData.instance(j));
				testSet.get(j).predictedSense = testSet.senses.elementAt((int)classifier.classifyInstance(testData.instance(j)))+"";
				
				results.add(testSet.get(j).kwicID,testSet.get(j).toHumanString(),testSet.get(j).predictedSense,testSet.get(j).sense);
				
				//if (testSet.get(j).predictedSense.equalsIgnoreCase(testSet.get(j).sense)) {
					
				//}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (save) {
			WSDCorpus.saveTXT(testSet, testSet.corpusName);
			System.out.println(results.getResult());
			System.out.println(results.detailedResults());
		}
	//	System.out.println(correct + "/" + testSet.size());
		testSet.clear(); 
	
		
	}
	
	

}