package ciranda;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.Iterator;

import ciranda.classify.ModelFactory;
import ciranda.features.CommitFE;
import ciranda.features.DdataFE;
import ciranda.features.DeliverFE;
import ciranda.features.FeatureExtractor;
import ciranda.features.MeetFE;
import ciranda.features.ProposeFE;
import ciranda.features.RequestFE;
import ciranda.utils.CirandaUtils;
import edu.cmu.minorthird.classify.ClassLabel;
import edu.cmu.minorthird.classify.ExampleSchema;
import edu.cmu.minorthird.classify.Instance;
import edu.cmu.minorthird.text.Span;
import edu.cmu.minorthird.text.TextBase;
import edu.cmu.minorthird.text.TextBaseLoader;
import edu.cmu.minorthird.text.TextLabels;

/**
 * @author Vitor R. Carvalho
 *
 * Predicts the act of an email message. 
 * Also gives the confidence in the prediction
 * 
 * Usage:
 *  SpeechAct sa = new SpeechAct();
 *  sa.loadMessage(bodyOfMessage1); //bodyOfMessage as String
 *  boolean req = sa.isRequest(); //bodyOfMessage1 contains a Request or not
 *  double conf = sa.getRequestConfidence(); //confidence in the Request prediction 
 * 
 *  boolean cmt = sa.isCommit(); //bodyOfMessage1 contains a Commit or not
 * ...
 *  
 *  //if more than 1 message need to be classified, don't create another SpeechAct object
 *  //just load the next messages in the same SpeechAct object
 *
 *  sa.loadMessage(bodyOfMessage2); // 
 *  boolean req = sa.isRequest(); //decision on bodyOfMEssage2
 * 
 *  
 */
public class SpeechAct {
	private String body;
	private ModelFactory factory = new ModelFactory();
	public SpeechAct(){;}
	
	/**
	* Loads body of email messages. Please remove header information. 
	* Also, for more accurate classification:
	*  1- please remove FWD parts of messages \
	*  2- please remove quotes from previous messages(Reply-to lines)
	*
	*/
	public void loadMessage(String _body){
		body = _body;
	}
	
	public boolean hasRequest(){
		FeatureExtractor fe = new RequestFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getRequestClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getRequestConfidence(){
		FeatureExtractor fe = new RequestFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getRequestClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	public boolean hasDeliver(){
		FeatureExtractor fe = new DeliverFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getDeliveryClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getDeliverConfidence(){
		FeatureExtractor fe = new DeliverFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getDeliveryClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	public boolean hasCommit(){
		FeatureExtractor fe = new CommitFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getCommitClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getCommitConfidence(){
		FeatureExtractor fe = new CommitFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getCommitClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	public boolean hasPropose(){
		FeatureExtractor fe = new ProposeFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getProposeClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getProposeConfidence(){
		FeatureExtractor fe = new ProposeFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getProposeClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	public boolean hasMeet(){
		FeatureExtractor fe = new MeetFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getMeetClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getMeetConfidence(){
		FeatureExtractor fe = new MeetFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getMeetClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	public boolean hasDdata(){
		FeatureExtractor fe = new DdataFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getDdataClassifier().classification(ins);
		return clab.isPositive();
	}
	
	public double getDdataConfidence(){
		FeatureExtractor fe = new DdataFE(body);
		Instance ins = fe.string2Instance();
		ClassLabel clab = factory.getDdataClassifier().classification(ins);
		if(clab.isNegative()){return 1 - clab.getProbability(ExampleSchema.POS_CLASS_NAME);}
		else return clab.getProbability(ExampleSchema.POS_CLASS_NAME);
	}
	
	private static void usage(){
		System.out.println("Usage: SpeechAct directoryName (for instance, SpeechAct ../myEmails)");
		System.out.println("\n1 msg per file. Body of email msgs should be in between <body> </body> tags");
		//System.out.println("Set of acts: Req,Dlv,Cmt,Prop,ReqAmdProp,DlvCmt,Meet,Ddata");		
	}

	public static void main(String[] args) {
		if(args.length<1) {usage(); System.exit(0);}
//		String act = args[0];
		String dir = args[0];
		SpeechAct sa = new SpeechAct();
//		sa.loadMessage("hey jude, do you want to come with me to the party?" +
//				"it's goig to be a lot of fun. let me know asap, ok?" +
//				"cheers, jukebox");
//		System.out.println("Msg1: Req = "+sa.isRequest()+"  , Confidence= "+sa.getRequestConfidence());
//		sa.loadMessage("hey jude, i just wanna let you know that everything is " +
//				"taken care of. I'll be there by 7 on Monday" +
//				"best regards, zomjio");
//		System.out.println("Msg2: Req = "+sa.isRequest()+"  , Confidence= "+sa.getRequestConfidence());
		
		
		//load data from directory
		TextBaseLoader loader = new TextBaseLoader(TextBaseLoader.DOC_PER_FILE,false,false);
		try {
			loader.load(new File(dir));
		} catch (Exception e) {
			e.printStackTrace();
		}
		TextLabels tl = loader.getLabels();		
		TextBase tb = tl.getTextBase();
		int ija = 0;
		for(Iterator it = tb.documentSpanIterator(); it.hasNext(); ){
			ija++;
			Span docspan = (Span)it.next();
			String id = docspan.getDocumentId();
//			System.out.println("BEFORE"+docspan.asString());
			String body = "";
			if(CirandaUtils.hasBodyTag(docspan.asString())){
				body = CirandaUtils.getBody(docspan.asString());
			}
			else body = docspan.asString();
			sa.loadMessage(body);
//			System.out.println("File #"+ija+" : "+id+"  ------------------------);
			System.out.println("file #"+ija+" "+id+" : Req = "+sa.hasRequest()+"  , Confidence= "+sa.getRequestConfidence());
			System.out.println("file #"+ija+" "+id+" : Dlv = "+sa.hasDeliver()+"  , Confidence= "+sa.getDeliverConfidence());
			System.out.println("file #"+ija+" "+id+" : Cmt = "+sa.hasCommit()+"  , Confidence= "+sa.getCommitConfidence());
			System.out.println("file #"+ija+" "+id+" : Prop = "+sa.hasPropose()+"  , Confidence= "+sa.getProposeConfidence());
			System.out.println("file #"+ija+" "+id+" : Meet = "+sa.hasMeet()+"  , Confidence= "+sa.getMeetConfidence());
			System.out.println("file #"+ija+" "+id+" : Ddata = "+sa.hasDdata()+"  , Confidence= "+sa.getDdataConfidence());
			System.out.println("*");
		}
	}
}
