package dr.app.beagle.tools.parsers;

import dr.app.beagle.evomodel.sitemodel.BranchSubstitutionModel;
import dr.app.beagle.evomodel.sitemodel.GammaSiteRateModel;
import dr.app.beagle.evomodel.sitemodel.HomogenousBranchSubstitutionModel;
import dr.app.beagle.evomodel.substmodel.FrequencyModel;
import dr.app.beagle.evomodel.substmodel.SubstitutionModel;
import dr.app.beagle.tools.BeagleSequenceSimulator;
import dr.evolution.alignment.Alignment;
import dr.evolution.datatype.Codons;
import dr.evolution.datatype.Nucleotides;
import dr.evolution.sequence.Sequence;
import dr.evomodel.branchratemodel.BranchRateModel;
import dr.evomodel.branchratemodel.DefaultBranchRateModel;
import dr.evomodel.tree.TreeModel;
import dr.xml.AbstractXMLObjectParser;
import dr.xml.XMLObject;
import dr.xml.XMLParseException;
import dr.xml.XMLSyntaxRule;

/**
 * @author Filip Bielejec
 * @version $Id$
 */
public class BeagleSequenceSimulatorParser extends AbstractXMLObjectParser {

	public static final String BEAGLE_SEQUENCE_SIMULATOR = "beagleSequenceSimulator";
	public static final String REPLICATIONS = "replications";
	public static final String SITE_MODEL = "siteModel";
	
	@Override
	public String getParserName() {
		return BEAGLE_SEQUENCE_SIMULATOR;
	}

	@Override
	public String getParserDescription() {
		return "Beagle sequence simulator";
	}

	@Override
	public Class<Alignment> getReturnType() {
		return Alignment.class;
	}

	@Override
	public XMLSyntaxRule[] getSyntaxRules() {
		
//		return new XMLSyntaxRule[] {
//				new ElementRule(TreeModel.class),
//				new ElementRule(BranchSubstitutionModel.class),
//				new ElementRule(GammaSiteRateModel.class),
////				 new ElementRule(SITE_MODEL, new XMLSyntaxRule[]{new ElementRule(BranchSubstitutionModel.class)}, false),
//				new ElementRule(BranchRateModel.class, true),
//				new ElementRule(FrequencyModel.class),
//				new ElementRule(Sequence.class, true),
//				AttributeRule.newIntegerRule(REPLICATIONS) };
		
		return null;
		
	}//END: getSyntaxRules

	@Override
	public Object parseXMLObject(XMLObject xo) throws XMLParseException {

		TreeModel tree = (TreeModel) xo.getChild(TreeModel.class);
		
		GammaSiteRateModel siteModel = (GammaSiteRateModel) xo.getChild(GammaSiteRateModel.class);
		FrequencyModel freqModel = (FrequencyModel) xo.getChild(FrequencyModel.class);
		Sequence ancestralSequence = (Sequence) xo.getChild(Sequence.class);
		int replications = xo.getIntegerAttribute(REPLICATIONS);

		BranchRateModel rateModel = (BranchRateModel) xo.getChild(BranchRateModel.class);
		if (rateModel == null) {
			rateModel = new DefaultBranchRateModel();
		}
		
		// TODO check this for cast errors
		BranchSubstitutionModel branchSubstitutionModel = (BranchSubstitutionModel) xo.getChild(BranchSubstitutionModel.class);
		if (branchSubstitutionModel == null) {
			SubstitutionModel substitutionModel = (SubstitutionModel) xo.getChild(SubstitutionModel.class);
			branchSubstitutionModel = new HomogenousBranchSubstitutionModel(substitutionModel, freqModel);
		}
		
		BeagleSequenceSimulator s = new BeagleSequenceSimulator(tree, //
				branchSubstitutionModel, //
				siteModel, //
				rateModel, //
				freqModel, //
				replications //
		);

		if (ancestralSequence != null) {

			if (ancestralSequence.getLength() != 3 * replications && freqModel.getDataType() instanceof Codons) {

				throw new RuntimeException("Ancestral codon sequence has "
						+ ancestralSequence.getLength() + " characters "
						+ "expecting " + 3*replications + " characters");

			} else if (ancestralSequence.getLength() != replications && freqModel.getDataType() instanceof Nucleotides) {

				throw new RuntimeException("Ancestral nuleotide sequence has "
						+ ancestralSequence.getLength() + " characters "
						+ "expecting " + replications + " characters");

			} else {

				s.setAncestralSequence(ancestralSequence);

			}// END: dataType check
		}// END: ancestralSequence check

		return s.simulate();

	}// END: parseXMLObject

}// END: class

@@ -31,16 +31,50 @@
 rsers;%0A%0A
+import java.util.logging.Logger;%0A%0A
 import d
@@ -122,32 +122,32 @@
 stitutionModel;%0A
-
 import dr.app.be
@@ -2124,16 +2124,38 @@
 tion %7B%0A%0A
+%09%09String msg = %22%22;%0A%09%09%0A
 %09%09TreeMo
@@ -2514,17 +2514,111 @@
 TIONS);%0A
+%09%09msg += %22%5Cn  %22 + replications + ( (replications %3E 1) ? %22 replications %22 : %22 replication%22);%0A%09%09
 %0A
-
 %09%09Branch
@@ -2765,16 +2765,160 @@
 odel();%0A
+%09%09%09msg += %22%5Cn  %22 + %22default branch rate model with rate of 1.0%22;%0A%09%09%7D else %7B%0A%09%09%09msg += %22%5Cn  %22 + rateModel.getModelName() + %22 branch rate model%22;%0A
 %09%09%7D%0A%09%09%0A%09
@@ -4231,16 +4231,145 @@
  check%0A%0A
+%09%09 if (msg.length() %3E 0) %7B%0A%09            Logger.getLogger(%22dr.evomodel%22).info(%22Using Beagle Sequence Simulator: %22 + msg);%0A%09%09 %7D%0A%09%09%0A
 %09%09return

print some logging messages