/*------------------------------------------------------------------------*/

function readNEXUS_partitionInfo (dummy)
{
	ExecuteAFile 	(HYPHY_LIB_DIRECTORY + "TemplateBatchFiles" + DIRECTORY_SEPARATOR + "TreeTools.ibf");
	ExecuteAFile 	(HYPHY_LIB_DIRECTORY + "TemplateBatchFiles" + DIRECTORY_SEPARATOR + "Utility" + DIRECTORY_SEPARATOR + "ReadDelimitedFiles.bf");

	mySplits 		 = {};
	myTrees  		 = {};
	treeStrings		 = {};
	splitCoordinates = {};

	for (_k2 = 0; _k2 < _pCount; _k2 = _k2 + 1)
	{
		if (Columns(DATA_FILE_PARTITION_MATRIX) == 0)
		{
			mySplits[_k2] = Format(0,10,0)+"-"+Format(ds_1.sites-1,10,0);
		}
		else
		{
			_pos = splitOnRegExp(DATA_FILE_PARTITION_MATRIX[1][_k2],"\\-");
			_r1 = (0+_pos[0])%3;
			if (_r1 == 2)
			{
				_r1 = (0+_pos[0])$3*3+3;
			}
			else
			{
				_r1 = (0+_pos[0])$3*3;
			}
			_r2 = (0+_pos[1])%3;
			if (_r2 >=1)
			{
				_r2 = (0+_pos[1])$3*3+2;
			}
			else
			{
				_r2 = (0+_pos[1])$3*3-1;
			}
			mySplits[_k2]		 					 = Format(_r1,10,0)+"-"+Format(_r2,10,0);
			splitCoordinates[Abs(splitCoordinates)]	 = {{_r1__,_r2__}};
		}
		ts			  = NEXUS_FILE_TREE_MATRIX[_k2][1];
		UseModel 		(USE_NO_MODEL);
		Tree testTree = ts;
		testTreeAVL   = testTree^0;
		myTrees[_k2]  = KillInternalZeroBranchLengths (testTreeAVL);
	}
	return 0;
}


/*------------------------------------------------------------------------*/

function constructLF (lf_name, filter_pref, tree_pref, part_count)
{
	lfDefCommand = "";
	lfDefCommand * 128;
	lfDefCommand * ("LikelihoodFunction  " + lf_name + " = (" + filter_pref + "_1," + tree_pref + "_1");

	for (_partID = 2; _partID <= part_count; _partID = _partID + 1)
	{
		lfDefCommand * ("," + filter_pref + "_" + _partID + "," + tree_pref + "_" +  _partID);
	}

	lfDefCommand * ");";
	lfDefCommand * 0;
	return lfDefCommand;
}

/*------------------------------------------------------------------------*/

function populateTrees (tree_pref, part_count)
{
	lfDefCommand = "";
	lfDefCommand * 128;

	for (_partID = 1; _partID <= part_count; _partID = _partID + 1)
	{
		lfDefCommand * ("Tree " + tree_pref + "_" + _partID + " = " + treeStrings[_partID] + ";\n");
	}

	lfDefCommand * 0;
	ExecuteCommands (lfDefCommand);
	return 0;
}

/*------------------------------------------------------------------------*/

function copyTreeBL (tree_pref, tree_pref_2, scaler_pref, part_count)
{
	lfDefCommand = "";
	lfDefCommand * 128;

	for (_partID = 1; _partID <= part_count; _partID = _partID + 1)
	{
		lfDefCommand * ("Tree " + tree_pref + "_" + _partID + " = " + treeStrings[_partID] + ";\nglobal " + scaler_pref + "_" + _partID + "=1;");

		lfDefCommand * ("ReplicateConstraint(\"this1.?.?:=" +
											scaler_pref +
											"_" +
											_partID +
											"*this2.?.?__\","+
											tree_pref + "_" + _partID + "," +
											tree_pref_2 + "_" + _partID + ");");
	}

	lfDefCommand * 0;
	ExecuteCommands (lfDefCommand);
	return 0;
}

/*------------------------------------------------------------------------*/


if (_runAsFunctionLibrary != 1)
{
	fileCount	= 0;
	while (fileCount < 1)
	{
		fprintf (stdout, "How many datafiles are to be analyzed (>=1):?");
		fscanf  (stdin, "Number", fileCount);
		fileCount = fileCount $ 1;
	}

	totalCodonCount  = 0;
	totalCharCount	 = 0;
	totalUniqueSites = 0;
	treeStrings		 = {};
	splitCoordinates = {};

	if (Abs(GeneticCodeExclusions) == 0)
	{
		GeneticCodeExclusions = "";
	}


	for (fileID = 1; fileID <= fileCount; fileID = fileID + 1)
	{
		fprintf (stdout, "\nReading input file ", fileID, "/", fileCount, "\n");
		SetDialogPrompt ("Please specify codon data #" + fileID + ":");

		ExecuteCommands (
		"DataSet				ds_" +fileID + " = ReadDataFile (PROMPT_FOR_FILE);");

        if (fileID == 1) {
                _base_file_path = LAST_FILE_PATH;
        }

		if (fileCount == 1)
		{
			_pCount = Rows(NEXUS_FILE_TREE_MATRIX);
			if ((_pCount == Columns(DATA_FILE_PARTITION_MATRIX) && Columns(DATA_FILE_PARTITION_MATRIX)) || _pCount == 1)
			{
				fileCount = _pCount;
				DataSet 	ds_0 = ReadDataFile (LAST_FILE_PATH);
				readNEXUS_partitionInfo (0);
				for (fileID = 1; fileID <= fileCount; fileID = fileID + 1)
				{
					DataSetFilter filteredData = CreateFilter (ds_0,3,mySplits[fileID-1],,GeneticCodeExclusions);
					Export (baseFPath,filteredData);

					if (_doAAcids == 0)
					{
						codonComponent = "DataSetFilter filteredData_" + fileID + " = CreateFilter (ds_"+fileID +",3,\"\",\"\",GeneticCodeExclusions);totalCharCount=totalCharCount+filteredData_"+fileID+".sites*filteredData_"+fileID+".species;totalCodonCount=totalCodonCount+filteredData_"+fileID+".sites;totalUniqueSites=totalUniqueSites+Columns(filteredData_"+fileID+".site_freqs);";
					}
					else
					{
						codonComponent = "totalCharCount=totalCharCount+nucData_"+fileID+".sites*nucData_"+fileID+".species;totalCodonCount=totalCodonCount+nucData_"+fileID+".sites;totalUniqueSites=totalUniqueSites+Columns(nucData_"+fileID+".site_freqs);";
					}
					ExecuteCommands (
									"DataSet				ds_" +fileID + " = ReadFromString (baseFPath);"+
									"fprintf (stdout,\"\\n\",ds_" + fileID + ");"+
									"DataSetFilter nucData_" + fileID + " = CreateFilter (ds_"+fileID +",1);"+
									codonComponent);
					treeString = myTrees[fileID-1];
					ExecuteCommands ("treeString_" + fileID + " = treeString;");
					treeStrings[fileID] = treeString;
				}
				break;
			}
		}


		if (_doAAcids == 0)
		{
			codonComponent = "DataSetFilter filteredData_" + fileID + " = CreateFilter (ds_"+fileID +",3,\"\",\"\",GeneticCodeExclusions);totalCharCount=totalCharCount+filteredData_"+fileID+".sites*filteredData_"+fileID+".species;totalCodonCount=totalCodonCount+filteredData_"+fileID+".sites;totalUniqueSites=totalUniqueSites+filteredData_"+fileID+".unique_sites;";
		}
		else
		{
			codonComponent = "totalCharCount=totalCharCount+nucData_"+fileID+".sites*nucData_"+fileID+".species;totalCodonCount=totalCodonCount+nucData_"+fileID+".sites;totalUniqueSites=totalUniqueSites+nucData_"+fileID+".unique_sites;";
		}
		ExecuteCommands ("fprintf (stdout,\"\\n\",ds_" + fileID + ");DataSetFilter nucData_" + fileID + " = CreateFilter (ds_"+fileID +",1);"+codonComponent);
		#include								   "queryTree.bf";
		ExecuteCommands ("treeString_" + fileID + " = treeString;");
		treeStrings[fileID] = treeString;
	}

	if (_doAAcids)
	{
		overallFrequencies 		  = {20,1};
	}
	else
	{
		positionFrequencies       = {4,3};
		overallFrequencies 		  = {4,1};
	}

	for (fileID = 1; fileID <= fileCount; fileID = fileID + 1)
	{
		if (_doAAcids)
		{
			ExecuteCommands 	  		("HarvestFrequencies (ts, nucData_"+fileID+",1,1,1);cfs = nucData_"+fileID+".sites;");
		}
		else
		{
			ExecuteCommands 	  		("HarvestFrequencies (tp, filteredData_"+fileID+",3,1,1);HarvestFrequencies (ts, filteredData_"+fileID+",1,1,1);cfs = filteredData_"+fileID+".sites;");
			positionFrequencies 		= positionFrequencies 		 + tp*(cfs/totalCodonCount);
		}
		overallFrequencies  		= overallFrequencies + ts*(cfs/totalCodonCount);
	}
}
