RequireVersion ("0.9920060502");

#include "ibfs/char_colors.def";

_idx = "`HYPHY_LIB_DIRECTORY`TemplateBatchFiles`DIRECTORY_SEPARATOR`Utility`DIRECTORY_SEPARATOR`GrabBag.bf";
ExecuteCommands ("#include\"`_idx`\";");
_idx = "`HYPHY_LIB_DIRECTORY`TemplateBatchFiles`DIRECTORY_SEPARATOR`Utility`DIRECTORY_SEPARATOR`PostScript.bf";
ExecuteCommands ("#include\"`_idx`\";");

_seqCount 		= Columns(_DATAPANEL_SELECTED_SEQUENCES_);
_selFilters		= Columns(_DATAPANEL_SELECTED_FILTERS_);

if (_seqCount != 1)
{
	fprintf (stdout, "ERROR: This plug in-needs a single selected sequence to use as reference\n");
	return 0;
}

_unitSize 	   = _DATAPANEL_UNIT_SIZE_[0];

if (_unitSize!=1)
{
	fprintf (stdout, "ERROR: This plug-in can only accept filters with unit size of one\n");
	return 0;
}

_seqCount = _DATAPANEL_SELECTED_SEQUENCES_[0];
_baseName = _DATAPANEL_DATASET_NAME_;

_sequenceMapping = {};
_haveReference = -1;

for (_idx = 0; _idx < _seqCount; _idx = _idx + 1)
{
	_sequenceMapping[_DATAPANEL_SELECTED_SEQUENCES_[_idx]] = 1;
}

for (_idx = 0; _idx < _DATAPANEL_DATAFILTER_.species; _idx = _idx + 1)
{
	GetString (_sidx, _DATAPANEL_DATAFILTER_, _idx);
	if (_sidx % "Reference")
	{
		_haveReference = _idx;
	}
}
_exclusions    = _DATAPANEL_EXCLUSIONS_[0];


DataSetFilter _subset1 = CreateFilter (_DATAPANEL_DATAFILTER_,_unitSize,"",_sequenceMapping[speciesIndex] == 1 && speciesIndex != _haveReference,_exclusions);
DataSetFilter _subset2 = CreateFilter (_DATAPANEL_DATAFILTER_,_unitSize,"",_sequenceMapping[speciesIndex] == 0 && speciesIndex != _haveReference,_exclusions);

_underMap = {};
if (_selFilters == 3)
{
	ExecuteCommands ("GetDataInfo (_under1,"+_DATAPANEL_SELECTED_FILTERS_[1]+",0);GetDataInfo (_under2,"+_DATAPANEL_SELECTED_FILTERS_[2]+",0);");
	for (_idx = 0; _idx < Columns (_under1); _idx = _idx+1)
	{
		_underMap [_under1[_idx]] = 1;
	}
	for (_idx = 0; _idx < Columns (_under2); _idx = _idx+1)
	{
		_underMap [_under2[_idx]] = _underMap [_under2[_idx]] + 2;
	}
}

_font_size  = 12;
_char_space = _font_size*1.1$1;
_page_w	    = 612;
_page_h     = 792;
_atom		= 5;
_seqCaps	= {};

_seqCaps[0] = "SRC";
_seqCaps[1] = "RCP";
_seqCaps[2] = "HXB2";

fprintf (stdout, "Name the selected sequence group:");
fscanf  (stdin, "String", _idx);
_seqCaps[0] = _idx;
fprintf (stdout, "Name the other sequence group:");
fscanf  (stdin, "String", _idx);
_seqCaps[1] = _idx;

_capOffset	= (Max(Abs(_seqCaps[0]),Max(Abs(_seqCaps[1]),Abs(_seqCaps[2])))-1)*_font_size;

DEFAULT_FILE_SAVE_NAME = _baseName + ".ps";
SetDialogPrompt 	  ("Save PostScript graphics to:");

fprintf (PROMPT_FOR_FILE,CLEAR_FILE,_HYPSPageHeader (_page_w,_page_h,"Character Plot for "+_baseName),
							_HYPSSetFont ("Courier",_font_size),
							"/dmx 6 array currentmatrix def\n",
							"/sshift fs 2 idiv fs add def\n",
							"/setb {0 0 0 setrgbcolor} def\n",
							"/dobox {setrgbcolor newpath 2 copy moveto 4 -1 roll exch 2 copy lineto exch 4 -1 roll 2 copy lineto 4 -1 roll exch lineto pop pop closepath} def\n",
							"/flbx  {dobox fill setb} def\n",
							"/stbx  {dobox stroke setb} def\n",
							"/drln  {setrgbcolor newpath moveto lineto stroke setb} def\n",
							"/drawletter {translate scale newpath 0 0 moveto false charpath fill dmx setmatrix translate 0.4 0.4 scale newpath sshift 0 moveto  false charpath fill dmx setmatrix} def\n"
);

outFile = LAST_FILE_PATH;

_page_w		= _page_w-_capOffset;
_selFilters		= Columns(_DATAPANEL_SELECTED_FILTERS_);


GetDataInfo (_charHandles, _DATAPANEL_DATAFILTER_, "CHARACTERS");
_ccount  = Columns (_charHandles);
_unit    = {1,_ccount}["1"];
_char_per_line  = _page_w / _char_space $ _atom * _atom;
if (_char_per_line == 0)
{
	fprintf (stdout, "\nERROR: At least ",_atom," characters must fit in a line; reduce font size in 'Character Plot' source\n");
}
else
{
	fprintf (stdout, "\n", _char_per_line, " characters per line\n");
}

GetDataInfo (_dupInfo, _subset1);
_result_cache1 = {};
_maxD		   = 0;
_dbyLine1 	   = {};

for (_idx = 0; _idx < _subset1.sites; _idx = _idx + 1)
{
	_siteInfo = {_ccount, 2};
	_cCounter = {_ccount, 1};
	for (_sidx = 0; _sidx < _subset1.species; _sidx = _sidx + 1)
	{
		GetDataInfo (_thisChar, _subset1, _sidx, _dupInfo[_idx]);
		/* don't count gaps */
		if (Abs (_thisChar) != Sqrt (_ccount))
		{
			_cCounter = _cCounter + _thisChar*(1/(_unit*_thisChar)[0]);
		}
	}
	_siteInfo = _siteInfo ["_MATRIX_ELEMENT_ROW_ * _MATRIX_ELEMENT_COLUMN_ + (1-_MATRIX_ELEMENT_COLUMN_)*_cCounter[_MATRIX_ELEMENT_ROW_]"]%0;
	for (_sidx = _ccount-1; _sidx >= 0; _sidx = _sidx - 1)
	{
		if (_siteInfo[_sidx][0] == 0)
		{
			break;
		}
	}
	_result_cache1[_idx] = _siteInfo[{{_sidx+1,0}}][{{_ccount-1,1}}];
	_sidx = Rows (_result_cache1[_idx]);
	
	if (_sidx > _maxD)
	{
		_maxD = _sidx;
	}

	if ((_idx + 1)%_char_per_line==0 || _idx == _subset1.sites - 1)
	{
		_dbyLine1 [Abs(_dbyLine1)] = _maxD;
		_maxD = 0;
	}	
}

GetDataInfo (_dupInfo, _subset2);
_result_cache2 = {};
_maxD		   = 0;
_dbyLine2 	   = {};

for (_idx = 0; _idx < _subset2.sites; _idx = _idx + 1)
{
	_siteInfo = {_ccount, 2};
	_cCounter = {_ccount, 1};
	for (_sidx = 0; _sidx < _subset2.species; _sidx = _sidx + 1)
	{
		GetDataInfo (_thisChar, _subset2, _sidx, _dupInfo[_idx]);
		/* don't count gaps */
		if (Abs (_thisChar) != Sqrt (_ccount))
		{
			_cCounter = _cCounter + _thisChar*(1/(_unit*_thisChar)[0]);
		}
	}
	_siteInfo = _siteInfo ["_MATRIX_ELEMENT_ROW_ * _MATRIX_ELEMENT_COLUMN_ + (1-_MATRIX_ELEMENT_COLUMN_)*_cCounter[_MATRIX_ELEMENT_ROW_]"]%0;
	for (_sidx = _ccount-1; _sidx >= 0; _sidx = _sidx - 1)
	{
		if (_siteInfo[_sidx][0] == 0)
		{
			break;
		}
	}
	_result_cache2[_idx] = _siteInfo[{{_sidx+1,0}}][{{_ccount-1,1}}];
	_sidx = Rows (_result_cache2[_idx]);
	
	if ((_idx + 1)%_char_per_line==0 || _idx == _subset2.sites - 1)
	{
		_dbyLine2 [Abs(_dbyLine2)] = _maxD;
		_maxD = 0;
	}
	
	if (_sidx > _maxD)
	{
		_maxD = _sidx;
	}
}

if (_haveReference >= 0)
{
	_result_ref = {};
	GetDataInfo (_dupInfo, _DATAPANEL_DATAFILTER_);
	for (_idx = 0; _idx < _DATAPANEL_DATAFILTER_.sites; _idx = _idx + 1)
	{
		_cCounter = {_ccount, 1};
		_siteInfo = {_ccount, 2};
		
		GetDataInfo (_thisChar, _DATAPANEL_DATAFILTER_, _haveReference, _dupInfo[_idx]);
		/* don't count gaps */
		if (Abs (_thisChar) != Sqrt (_ccount))
		{
			_cCounter = _cCounter + _thisChar*(1/(_unit*_thisChar)[0]);
			_siteInfo = _siteInfo ["_MATRIX_ELEMENT_ROW_ * _MATRIX_ELEMENT_COLUMN_ + (1-_MATRIX_ELEMENT_COLUMN_)*_cCounter[_MATRIX_ELEMENT_ROW_]"]%0;
			_result_ref[_idx] = _siteInfo[Rows(_siteInfo)-1][1] + 1;
		}
	}
}

/* now for the plotter */

_current_x 	  = _capOffset;
_current_y	  = _page_h-(2+(_haveReference>=0))*_font_size;
_cl			  = 0;
_current_y2	  = _current_y - _dbyLine1 [0]*_font_size;

for (_idx = 0; _idx < _DATAPANEL_DATAFILTER_.sites; _idx = _idx + 1)
{
	_cCounter  = _result_cache1[_idx];
	_cCounter2 = _result_cache2[_idx];
	
	if (_underMap[_idx])
	{
		if (_underMap[_idx] != 2)
		{
			fprintf (outFile, _current_x, " ", _current_y-1, " ", _current_x + _char_space, " ", _current_y-1, " 0 0 0 drln\n");
		}
		if (_underMap[_idx] >= 2)
		{
			fprintf (outFile, _current_x, " ", _current_y2-1, " ", _current_x + _char_space, " ", _current_y2-1, " 0 0 0 drln\n");
		}
	}

	if (Rows (_cCounter) == 1 && Rows (_cCounter2) == 1)
	{
		if (_cCounter[0][1] != _cCounter2[0][1])
		{
			fprintf (outFile, _current_x, " ", _current_y+_font_size-_font_size$4-1, " ", _current_x + _char_space , " ", _current_y - _dbyLine1[_cl]*_font_size - 2, " 0.2 0.2 0.2 stbx\n");
		}
	}
	
	if (Rows(_cCounter))
	{
		for (_sidx = Rows(_cCounter)-1; _sidx >= 0; _sidx = _sidx - 1)
		{
			_siteInfo = _current_y-_font_size*(Rows(_cCounter)-1-_sidx);
			_my_c     = _charHandles[_cCounter[_sidx][1]];
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, _charColorList[_my_c], " setrgbcolor\n");
			}
			fprintf (outFile, "(",_cCounter[_sidx][0],") ", _current_x, " ",_siteInfo," (",_my_c,") 1 1 ", _current_x, " ", _siteInfo, " drawletter\n");
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, "setb\n");
			}
		}
	}
	else
	{
		fprintf (outFile, "( ) ", _current_x, " ",_current_y," (-) 1 1 ", _current_x, " ", _current_y, " drawletter\n");
	}
	
	if (Rows(_cCounter2))
	{
		for (_sidx = Rows(_cCounter2)-1; _sidx >= 0; _sidx = _sidx - 1)
		{
			_siteInfo = _current_y2-_font_size*(Rows(_cCounter2)-1-_sidx);
			_my_c     = _charHandles[_cCounter2[_sidx][1]];
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, _charColorList[_my_c], " setrgbcolor\n");
			}
			fprintf (outFile, "(",_cCounter2[_sidx][0],") ", _current_x, " ",_siteInfo," (",_my_c,") 1 1 ", _current_x, " ", _siteInfo, " drawletter\n");
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, "setb\n");
			}
		}
	}
	else
	{
		fprintf (outFile, "( ) ", _current_x, " ",_current_y2," (-) 1 1 ", _current_x, " ", _current_y2, " drawletter\n");
	}
	
	
	if (_haveReference >= 0)
	{
		if (_result_ref[_idx])
		{
			_siteInfo = _current_y+_font_size;
			_my_c     = _charHandles[_result_ref[_idx]-1];
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, _charColorList[_my_c], " setrgbcolor\n");
			}
			fprintf (outFile, "() 0 0 (",_my_c,") 1 1 ", _current_x, " ", _siteInfo, " drawletter\n");
			
			if (Abs(_charColorList[_my_c]))
			{
				fprintf (outFile, "setb\n");
			}
		}
		else
		{
			fprintf (outFile, "( ) 0 0 (-) 1 1 ", _current_x, " ", _current_y+_font_size, " drawletter\n");
		}
		
	}
	
	_current_x = _current_x + _char_space;

	if ((_idx + 1)%_char_per_line==0 || _idx == _DATAPANEL_DATAFILTER_.sites-1)
	{
		_current_y = _current_y + _font_size;
		if (_idx == _DATAPANEL_DATAFILTER_.sites-1)
		{
			if (_DATAPANEL_DATAFILTER_.sites % _char_per_line == 0)
			{
				_startx = _char_per_line;
			}
			else
			{
				_startx = _DATAPANEL_DATAFILTER_.sites%_char_per_line$_atom*_atom;
			}
			_idx2 = _DATAPANEL_DATAFILTER_.sites-_DATAPANEL_DATAFILTER_.sites%_char_per_line;
		}
		else
		{
			_idx2 = _idx - _char_per_line + 1;
			_startx = _char_per_line;
		}
		
		fprintf (outFile, "0 ", _current_y - _font_size, " moveto (", _seqCaps[0], ") show\n");
		fprintf (outFile, "0 ", _current_y2, " moveto (", _seqCaps[1], ") show\n");
		
		if (_haveReference >= 0)
		{
			fprintf (outFile, "0 ", _current_y, " moveto (", _seqCaps[2], ") show\n");
			_current_y = _current_y + _font_size;
		}
		
		fprintf (outFile, _capOffset, " ", _current_y + _font_size * 4$5, " ", _capOffset + _char_space*(1+_char_per_line) , " ", _current_y - _font_size$4, " 0.9 0.9 0.9 flbx\n");
		for (_idx3 = _startx; _idx3 > 0; _idx3 = _idx3 - _atom)
		{
			fprintf (outFile, "( ) 0 0 (",_idx2+_idx3,") 0.9 0.9 ", _capOffset + (_idx3-1) * _char_space, " ", _current_y, " drawletter\n");
		}

		if (_haveReference >= 0)
		{
			_current_y = _current_y - _font_size;
		}

		_current_x = _capOffset; 
		_current_y  = _current_y - (2+_dbyLine1[_cl]+_dbyLine2[_cl]+(_haveReference>=0))*_font_size;
		_cl = _cl+1;
		_current_y2 = _current_y - _dbyLine1 [_cl]*_font_size;
		if (_current_y - (1+_dbyLine1[_cl]+_dbyLine2[_cl]+(_haveReference>=0))*_font_size < 0)
		{
			_current_y  = _page_h-(2+(_haveReference>=0))*_font_size;
			_current_y2 = _current_y - _dbyLine1 [_cl];
			fprintf (outFile, "showpage\n");
		}
	}
}

/*
fprintf (outFile, CLOSE_FILE);
*/

