#include "test.h"
#include "../../pnheaders/pns.h"
#include "../spnbox.h"

int main(int argc, char* argv[])
{	
	FILE* input;
	char IDesc[] = "matrix D, matrix Dm, matrix Dp, indexarray Tuc, indexarray Tuo, matrix L, matrix F, matrix C, arrayi b, arrayi m0, arrayi LB, arrayi UB, matrix H";
	char ODesc[] = "matrix Df, matrix Dfm, matrix Dfp, arrayi mso, string how, matrix Lf, matrix Cf";
	int *IFilled;
	int OFilled[8];
	int Transitions;
	matrix D, Dm, Dp, DDm, DDp, L, L_star, H, F, C, DNew, LD;
	int *b, *CD, *m0, *Tuc, *Tuo, *LB, *UB, *m1, *label0;
	int bnum, m0num, TucCount, TuoCount, LBnum, UBnum;
	pns plant1, plant2;

	linenf_r sol;
	MemoryManager memory;

	int i, j, Constraints;
	
	/*Get the input file pointer.*/
	if (! (input = ParseCmdLine(argc,argv)))
	{
		return 0;
	}
	memory = CreateMemoryManager(20, 20, 0, 0);
	
	/*Initialize the petri net output matrix to a zero-by-zero, needed because
	its dimensions are used later without checking to make sure it has been
	initialized. Just to prevent runtime errors. Will suppress the Tuc and Tuo
	output if a problem is given without any incidence matrices.*/	
	while (ParseStructure(input, IDesc, &IFilled, &memory, &D, &Dm, &Dp, &Tuc, &TucCount, &Tuo, &TuoCount, &L, &F, &C, &b, &bnum, &m0, &m0num, &LB, &LBnum, &UB, &UBnum, &H))/*,  ))*/
	{		
		/*Display the problem.*/
		Transitions = IFilled[0] ? NumberOfColumns(D) : (IFilled[1] ? NumberOfColumns(Dm) : 0);
		DisplayStructure(IDesc, IFilled, &D, &Dm, &Dp, Tuc, TucCount, Transitions, Tuo, TuoCount, Transitions, &L, &F, &C, b, bnum, m0, m0num, LB, LBnum, UB, UBnum, &H);
	
		/*Fill in the i/o matrices from the incidence matrix if applicable.*/
		FillDmDp(IFilled, &D, &Dm, &Dp, &memory);

		/*Convert disjunctive constraints to normal constraints, get new D L b m0*/
		label0 = mmalloc(&memory, D.nr * sizeof(int));
		for(j = 0; j < D.nc; j++) {
		  label0[j] = j+1;
		}
		plant1 = createpn("mD m0 label", D, m0, label0);
		disq2disj(&plant1, &L, &H, &plant2, &L_star);

		MAllocateMatrixType(&memory, 2, &LD, 2 * L_star.nr + 1, L_star.nc + L_star.nr);
		CD = mmalloc(&memory, (2 * L_star.nr + 1) * sizeof(int));
		m1 = mmalloc(&memory, (L_star.nr + L_star.nc) * sizeof(int));
		disj2normal(&plant2, &L_star, b, LB, UB, &DDm, &DDp, &LD, CD, m1);
		ManageMatrix(&memory, &DDm);
		ManageMatrix(&memory, &DDp);

		/*Do the constraint enforcement.*/
		sol = linenf(IFilled[1] ? &DDm : 0, IFilled[2] ? &DDp : 0, IFilled[5] ? &LD : 0, IFilled[8] ? CD : 0, IFilled[9] ? m1 : 0, IFilled[6] ? &F : 0, IFilled[7] ? &C : 0, IFilled[3] ? TucCount : 0, Tuc, IFilled[4] ? TuoCount : 0, Tuo);
		
		/*Get the list of which output parameters are present for display. Also 
		manage memory. (Defaults to nothing present)*/
		memset(OFilled, 0, sizeof(int) * 8);
		Constraints = 0;
		
		/*If there are no self-loops than optimize display by showing an incidence
		matrix instead of both the input and the output matrices.*/
		if (! HasSelfLoops(&sol.Dfm, &sol.Dfp))
		{
			DNew = SubtractMatrix(&sol.Dfp, &sol.Dfm, (matrix*) 2);
			ManageMatrix(&memory, &DNew);
			OFilled[0] = 1;
		}
		else
		{
			OFilled[1] = 1;
			OFilled[2] = 1;
		}				
		if (sol.ms0)
		{			
			OFilled[3] = 1;
		}
		if (sol.how)
		{
			OFilled[4] = 1;
		}
		if (sol.Lf.type)
		{
			OFilled[5] = 1;
			Constraints = NumberOfRows(sol.Lf);
		}
		if (sol.Cf.type)
		{
			OFilled[6] = 1;
			Constraints = NumberOfRows(sol.Cf);
		}
		if (sol.bf)
		{
			OFilled[7] = 1;
		}
		
		printf("Solution:\n");
		/*Display the result.*/
		DisplayStructure(ODesc, OFilled, &DNew, &sol.Dfm, &sol.Dfp, sol.ms0, NumberOfRows(sol.Dfm), sol.how, &sol.Lf, &sol.Cf);
		/*Display the per-constraint messages that are not OK.*/
		if (sol.dhow)
		{	
			for (i = 0; i < Constraints; i++)
			{
				if (strcmp(HOW_OK, sol.dhow[i]))
				{
					printf("Constraint %d: %s\n", i, sol.dhow[i]);
				}
			}
		}
		printf("---------------------------------------------------------------\n");
		FreeMemory(&memory);
		deallocpn(&plant1);
		deallocpn(&plant2);
		DeallocateLinenf(&sol);
		memory = CreateMemoryManager(15, 15, 0, 0);
	}
	FreeMemory(&memory);
	return 0;
}
