#include <string.h>
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

#include "FStatus.h"
#include "FNet.h"
#include "FPat.h"
#include "misc.h"

/////////////////////////// MAIN PROGRAM ///////////////////////////
int main(void)
{
	char ER[]="ERROR";

	const StrMaxLen=1024;

	char FTASK[]="recovering.tsk";
	ifstream tsk;
	char StrBuf[StrMaxLen];
	int str1,str2;
	
	char NET[]="NET=";
	char ParamNET[StrMaxLen];

	char PATB[]="PAT_BEGIN=";
	char ParamPATB[StrMaxLen];

	char PATE[]="PAT_END=";
	char ParamPATE[StrMaxLen];

	char PATEXT[]=".pat";

	char PAT_PATH[]="PATS\\";
	char NET_PATH[]="NETS\\";

	unsigned int nP, nPB, nPE;

	unsigned int ln1, ln2;
	
	const LoopMax=16;
	unsigned int lp;

	CFStatus FStatus("recovering.out");
	
	char sta[StrMaxLen], stb[StrMaxLen];
	char st1[StrMaxLen], st2[StrMaxLen], st3[StrMaxLen];

	int ret;

	
	//program
	cout << "Fursin Program - 'Recovering of patterns (Hopfield Network)'  (C)  V1.0\n";

	//reading file with task
	tsk.open(FTASK,ios::nocreate|ios::in);
	if (tsk==NULL)
	{
		FStatus.Set(ER,"Can't find file with task",true);
		return 1;
	}		

	//loop for sub-tasks
	do
	{
		// Getting first line -> "NET="
		str1=Rd(tsk, StrBuf, StrMaxLen);
		str2=GetParam(StrBuf, NET, ParamNET, StrMaxLen);
		if (str2!=0)
		{
err_quit:
			if (str2==-1) 
			{
				FStatus.Set(ER,"Empty line in file with task",true);
				return 1;
			}
			else if (str2==-2)
			{
				FStatus.Set(ER,"Line is too short in file with task",true);
				return 1;
			}
			else if (str2==-3)
			{
				FStatus.Set(ER,"Can't find reserved words in file with task",true);
				return 1;
			}
			return 1;
		}

		// Getting first line -> "PAT_BEGIN="
		str1=Rd(tsk, StrBuf, StrMaxLen);
		str2=GetParam(StrBuf, PATB, ParamPATB, StrMaxLen);
		if (str2!=0) goto err_quit;
		
		// Getting first line -> "PAT_END="
		str1=Rd(tsk, StrBuf, StrMaxLen);
		str2=GetParam(StrBuf, PATE, ParamPATE, StrMaxLen);
		if (str2!=0) goto err_quit;

		//Loading Network
		CFNet *pNet = new CFNet(ParamNET, NET_PATH, StrMaxLen);
		ret=pNet->Load();
		if (ret==-1)
		{
			FStatus.Set(ER,"Can't open file with neural network",true);
			return 1;
		}
		else if (ret==-2)
		{
			FStatus.Set(ER,"Unexpected end of file with neural network",true);
			return 1;
		}
					
		// Starting recovering
		ln1=strlen(ParamPATB);
		if (strlen(ParamPATE)!=ln1) 
		{
			FStatus.Set(ER,"Length of PAT_BEGIN<>length of PAT_END",true);
			return 1;
		}
		
		nPB=hextoint(ParamPATB);
		nPE=hextoint(ParamPATE);
	
		if (nPB>nPE) 
		{
			FStatus.Set(ER,"PAT_BEGIN > PAT_END",true);	
			return 1;
		}

		//Loop for patterns --------------------------------------
		
		for (nP=nPB; nP<=nPE; nP++)
		{
			strcpy(st1, PAT_PATH);
		
			itoa(nP, st2, 16);
			strupr(st2);
			ln2=strlen(st2);
			if (ln2<ln1)
			{
				strcpy(st3,"12345678901234567890123456789012");
				strnset(st3,'0',ln1-ln2);
				st3[ln1-ln2]='\0';
				strcat(st1,st3);
			}
		
			strcat(st1,st2);

			strcpy(sta,st1);
			strcat(sta,PATEXT);
			
			//Recovering -----------------------------------------
			for (lp=1; lp<=LoopMax; lp++)
			{
				itoa(lp, st2, 10);
				strupr(st2);
				ln2=strlen(st2);
				if (ln2<3)
				{
					strcpy(st3,"12345678901234567890123456789012");
					strnset(st3,'0',3-ln2);
					st3[3-ln2]='\0';
				}
				strcpy(stb,st1);
				strcat(stb,".");
				strcat(stb,st3);
				strcat(stb,st2);

				//Loading input pattern (sta)
				CFPat *pPatInp=new CFPat('.','O');
				ret=pPatInp->Load(sta);
				if (ret==-1)
				{
					FStatus.Set(ER,"Can't open file with pattern",true);
					return 1;
				}
				else if (ret==-2)
				{
					FStatus.Set(ER,"Unexpected end of file with pattern",true);
					return 1;
				}
				else if (ret==-3)
				{
					FStatus.Set(ER,"Unknown character in pattern",true);
					return 1;
				}
				
				//Making output pattern in RAM
				CFPat *pPatOut=new CFPat('.','O');
				ret=pPatOut->Create(pPatInp->DimX(),pPatInp->DimY());

				//Recovering from sta to stb
				ret=pNet->Recover(pPatInp, pPatOut);	
				if (ret==-1)
				{
					FStatus.Set(ER,"Dimensions of patterns are different",true);
					return 1;
				}
			
				//Saving output pattern (stb)
				ret=pPatOut->Save(stb);
				if (ret==-1)
				{
					FStatus.Set(ER,"Can't save output file with pattern",true);
					return 1;
				}

				//Comparing sta and stb
				bool z=pNet->Compare(pPatInp, pPatOut);
				delete pPatInp, pPatOut;

				if (z) break; //If equal then quit from loop
				
				//Not Equal
				strcpy(sta,stb); //sta <- stb, stb will be new
			}
		}

		//Read empty line or find EOF
		str1=Rd(tsk, StrBuf, StrMaxLen); 
	}
	while(str1>0);
		
	tsk.close();
	
	if (str1==-1)
	{
		FStatus.Set(ER,"String is too long in file with task",true);
		return 1;
	}
		
	FStatus.Set("OK","",false);

	return 0;
}
