#pragma once

#include "stdafx.h"

#include "Includes.h"

#include "Defines.h"

#include "BringUp.h"

#include "GUI_DefineFunctions.cpp"

using namespace std;

string FindRulesNumber(int i,int j,int Step,ifstream& Rules)
{
   string Value = "";
   int Bytes = GetByteParameters(i,j,Step);
   int TotalInt = 0;
   size_t loc1 = 0;
   size_t loc2 = 0;
   size_t loc5 = 0;
   int NegativeNumber = 0;
   size_t Distance = GetSpaces(i,j,Step);
   Line == "";
   if (i > rec_t_cnt - 1) {
      return "Fuckup";
   }
   if (Step == 0 && j == 0) {
      while ( getline(Rules, Line) ) {
         LineNumber++;
		   loc1 = Line.find(directive[i]);
	      if (loc1!=string::npos) {
			Debug << LineNumber << " <- LineNumber directive[i] -> " << directive[i] << '\n';
            getline(Rules, Line);
            LineNumber++;
            loc4 = 0;
				Debug << Line << " <- Line " << '\n';
				break;
         }
         if(LineNumber > 10000) {
            if (Debug_ == 1) {
               Debug << Line << '\n';
               Debug << " Label missing - FindRulesNumber " << '\n';
            }
				CallMessageBox("Line: ",Int2Str(LineNumber),"[",directive[i],"]"," expected.");
         }
      }
		return "Fuckup";
   } else if (Step == 0 && j > 0) {
      getline(Rules, Line);
      loc4 = 0;
      LineNumber++;
      Debug << Line << " Step-> " << Step << " i-> " << i  << " j-> " << j << " line jump " << '\n';
		return "Fuckup";
   } 
	Debug << Line << '\n';
   Debug << " Step-> " << Step << " i-> " << i  << " j-> " << j << " directive[i] -> " << directive[i] << '\n';
	loc2 = Line.find_first_of(',',loc4);
   if (loc2!=string::npos) {
      for (size_t l = loc2; l < (loc2 + Distance + 3); l++) {
         int One = 0;
         if ((char(Line.at(l)) == '-') && NegativeNumber == 0 && l > loc2 && l < (loc2 + Distance + 3)) {
            NegativeNumber = 1;
         }
         if ((IsCharInt(char(Line.at(l)))) && (l > loc2) && (One == 0)) {
            One = 1; 
            if (Step < step_max[i] - 1){
               loc5 = Line.find_first_of(',',l);
               if (loc5!=string::npos) {
                  if (loc5 - l < 8 && Bytes == 3) {
                     if (Debug_ == 1) {
                        Debug << Line << '\n';
                        Debug << " binary expected in FindRulesNumber " << '\n';
                     }
                     CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Binary string expected.");
                  }
                  Value = Line.substr(l,loc5 - l);
                  loc4 = l;
                  Line == "";
                  if (NegativeNumber == 1 && Bytes == 0) {
                     Debug << Value << " 0 before" << '\n';
                     int ValueInt = 256 - Str2Int(Value);
                     Value = Int2Str(ValueInt);
                     Debug << Value << " 0 after" << '\n';
                  }
                  if (NegativeNumber == 1 && Bytes == 1) {
                     Debug << Value << " 1 before" << '\n';
                     int ValueInt = 65536 - Str2Int(Value);
                     Value = "";
                     Value.append(Int2Str(ValueInt));
                     Debug << Value << " 1 after" << '\n';
                  }
						Debug << Value << " <-Value Step -> " << Step << " " << j << " <- j i -> " << i << '\n';
                  return Value;
               } else {
                  if (Debug_ == 1) {
                     Debug << Line << '\n';
                     Debug << " Second comma in FindRulesNumber " << l << " <-iterator " << loc4 << " <-loc4 Step-> " << Step << " " << i << " " << Line.length() << '\n';
                  }
						CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Comma expected.");
               }
            } else if (Step == step_max[i] - 1) {
               Debug << loc4 << '\n';
               loc5 = Line.find_first_of(';',l);
               Debug << char(Line.at(loc5)) << '\n';
               if (loc5!=string::npos) {
                  if (loc5 - l < 8 && Bytes == 3) {
                     if (Debug_ == 1) {
                        Debug << Line << '\n';
                        Debug << " binary expected in FindRulesNumber " << '\n';
                     }
                     CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Binary string expected.");
                  }
                  Value = Line.substr(l,loc5 - l);
                  if (i == 42) {
                     Debug << Value << '\n';
                  }
                  Debug << Value << " Step-> " << Step << "[" << directive[i] << "]" << j << " <-j" << '\n';
                  if (j + 1 == rec_count[i]) {
                     if (i == 7) {
                        Debug << " \n\n\n " << Line << " loc4-> " << loc4 << " Step-> " << Step << '\n';
                     }
                     getline(Rules, Line);
                     LineNumber++;
		               loc1 = Line.find(directive[rec_t_cnt]);
		               if (loc1!=string::npos) {
                        if (i == 7) {
                           Debug << " \n\n\n " << Line << " loc4-> " << loc4 << " Step-> " << Step << " i-> " << i << '\n';
                        }
                        loc4 = 0;
                        Line == "";
								if (NegativeNumber == 1 && Bytes == 0) {
									Debug << Value << " 0 before" << '\n';
									int ValueInt = 256 - Str2Int(Value);
									Value = Int2Str(ValueInt);
									Debug << Value << " 0 after" << '\n';
								}
								if (NegativeNumber == 1 && Bytes == 1) {
									Debug << Value << " 1 before" << '\n';
									int ValueInt = 65536 - Str2Int(Value);
									Value = "";
									Value.append(Int2Str(ValueInt));
									Debug << Value << " 1 after" << '\n';
								}
								return Value;
                     } else {
                        if (Debug_ == 1) {
                           Debug << Line << '\n';
                           Debug << " end missing - FindRulesNumber " << '\n';
									Debug << Line << '\n';
                        }
                        CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," [END] expected.");
                     }
                  } else {
                     Debug << Value << " end check " << '\n';
                     loc4 = 0;
                     Line == "";
                     if (NegativeNumber == 1 && Bytes == 0) {
                        Debug << Value << " 0 before" << '\n';
                        int ValueInt = 256 - Str2Int(Value);
                        Value = Int2Str(ValueInt);
                        Debug << Value << " 0 after" << '\n';
                     }
                     if (NegativeNumber == 1 && Bytes == 1) {
                        Debug << Value << " 1 before" << '\n';
                        int ValueInt = 65536 - Str2Int(Value);
                        Value = "";
                        Value.append(Int2Str(ValueInt));
                        Debug << Value << " 1 after" << '\n';
                     }
                     return Value;
                  }
               } else {
                  if (Debug_ == 1) {
                     Debug << Line << '\n';
                     Debug << " Second in FindRulesNumber " << '\n';
                  }
                  CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Semi-colon expected.");
               }
            }
         }
      }
      if (Value == "" ) {
         if (Debug_ == 1) {
            Debug << Line << '\n';
            Debug << " Number String empty in FindRulesNumber " << Distance << " Step " << Step << '\n';
         }
         CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Decimal Number expected.");
      } 
   } else {
      if (Debug_ == 1) {
         Debug << Line << '\n';
         Debug << " 1st in FindRulesNumber " << loc4 << " <-loc4 " << loc2 << " <-loc2 Step-> " << Step << " Line.length()-> " << Line.length() << '\n';
      }
      CallMessageBox("Line: ",Int2Str(LineNumber)," In ","[",CharArray2Str(directive[i]),"]"," section "," Comma expected.");
   }
   return "0";
}

int WriteBYTE(ofstream& OutputFile,int Hex,string Value)
{
   OutputFile.seekp(Hex,ios_base::beg);
   OutputFile.put(Str2Int(Value));
	Debug << " WriteBYTE Hex -> " << IntToHex(Hex) << " <- Hex Value -> " << Value << endl;
	return 0;
}

int WriteBitFlagHex8Bit(ofstream& OutputFile,int Hex,string Value)
{
   int TotalInt = 0;
	string TotalString = "";
   string ByteOneStr = "";
   string ByteTwoStr = "";
   string TotalHex = "";
   char TotalByteOne[3];
   char TotalByteTwo[3];
   char LowHex[3];
   char HighHex[3];
   int ByteOne = 0;
   int ByteTwo = 0;
   string ByteOne1 = "";
   string ByteTwo1 = "";
   TotalByteOne[0] = '\0';
   TotalByteOne[1] = '\0';
   TotalByteOne[2] = '\0';
   TotalByteOne[3] = '\0';
   TotalByteOne[4] = '\0';
   TotalByteTwo[0] = '\0';
   TotalByteTwo[1] = '\0';
   TotalByteTwo[2] = '\0';
   TotalByteTwo[3] = '\0';
   TotalByteTwo[4] = '\0';
   LowHex[0] = '\0';
   LowHex[1] = '\0';
   LowHex[2] = '\0';
   HighHex[0] = '\0';
   HighHex[1] = '\0';
   HighHex[2] = '\0';
   ByteOne = StringToBitFlag(Value);
	OutputFile.seekp(Hex,ios_base::beg);
	OutputFile.put(ByteOne);
	Debug << " WriteBitFlagHex8BitTest Fired bitstring-> " << ByteOne << " ByteOne " << Value << " Value " << endl;
   TotalInt = 0;
   ByteOneStr = "";
   ByteTwoStr = "";
   TotalHex = "";
   TotalByteOne[0] = '\0';
   TotalByteOne[1] = '\0';
   TotalByteOne[2] = '\0';
   TotalByteOne[3] = '\0';
   TotalByteOne[4] = '\0';
   TotalByteTwo[0] = '\0';
   TotalByteTwo[1] = '\0';
   TotalByteTwo[2] = '\0';
   TotalByteTwo[3] = '\0';
   TotalByteTwo[4] = '\0';
   LowHex[0] = '\0';
   LowHex[1] = '\0';
   LowHex[2] = '\0';
   HighHex[0] = '\0';
   HighHex[1] = '\0';
   HighHex[2] = '\0';
   ByteOne = 0;
   ByteTwo = 0;
   ByteOne1 = "";
   ByteTwo1 = "";
   return 0;
}

int WriteDWORD(ofstream& OutputFile,int Hex,string TotalString)
{
	int Zero = 0;
   int TotalInt = 0;
   string ByteOneStr = "";
   string ByteTwoStr = "";
   string TotalHex = "";
   char TotalByteOne[3];
   char TotalByteTwo[3];
   char LowHex[3];
   char HighHex[3];
   int ByteOne = 0;
   int ByteTwo = 0;
   string ByteOne1 = "";
   string ByteTwo1 = "";
   TotalByteOne[0] = '\0';
   TotalByteOne[1] = '\0';
   TotalByteOne[2] = '\0';
   TotalByteOne[3] = '\0';
   TotalByteOne[4] = '\0';
   TotalByteTwo[0] = '\0';
   TotalByteTwo[1] = '\0';
   TotalByteTwo[2] = '\0';
   TotalByteTwo[3] = '\0';
   TotalByteTwo[4] = '\0';
   LowHex[0] = '\0';
   LowHex[1] = '\0';
   LowHex[2] = '\0';
   HighHex[0] = '\0';
   HighHex[1] = '\0';
   HighHex[2] = '\0';
   TotalInt = Str2Int(TotalString);
   TotalHex = IntToHex(TotalInt);
   if (TotalHex.length() > 4) {
      TotalHex.erase(4);
   }
   if (TotalHex.length() == 4) {
      ByteTwoStr = TotalHex.substr(0,2);
      ByteOneStr = TotalHex.substr(2,2);
   }
   if (TotalHex.length() == 3) {
      if (HexToInt(TotalHex) <= 255) {
         ByteTwoStr = TotalHex.substr(0,2);
         ByteOneStr = TotalHex.substr(2,1);
      } else {
         ByteTwoStr = TotalHex.substr(0,1);
         ByteOneStr = TotalHex.substr(1,2);
      }
   }
   if (TotalHex.length() == 2) {
      ByteOneStr = TotalHex.substr(0,2);
      ByteTwoStr.append("0");
   }
   if (TotalHex.length() == 1) {
      ByteOneStr = TotalHex.substr(0,1);
      ByteTwoStr.append("0");
   }
	if (TotalHex.length() >= 3) {
		OutputFile.seekp(Hex,ios_base::beg);
		OutputFile.put(HexToInt(ByteOneStr));
		OutputFile.seekp(Hex + 1,ios_base::beg);
		OutputFile.put(HexToInt(ByteTwoStr));
	} else if (TotalHex.length() <= 2) {
		OutputFile.seekp(Hex,ios_base::beg);
		OutputFile.put(HexToInt(ByteOneStr));
		OutputFile.seekp(Hex + 1,ios_base::beg);
		OutputFile.put(Zero);
	}
	Debug << " WriteDWORD Fired HighValue-> " << IntToHex(ByteTwoStr) << " LoValue-> " << IntToHex(ByteOneStr) << " Total-> " << TotalHex << endl;
   TotalInt = 0;
   ByteOneStr = "";
   ByteTwoStr = "";
   TotalHex = "";
   TotalByteOne[0] = '\0';
   TotalByteOne[1] = '\0';
   TotalByteOne[2] = '\0';
   TotalByteOne[3] = '\0';
   TotalByteOne[4] = '\0';
   TotalByteTwo[0] = '\0';
   TotalByteTwo[1] = '\0';
   TotalByteTwo[2] = '\0';
   TotalByteTwo[3] = '\0';
   TotalByteTwo[4] = '\0';
   LowHex[0] = '\0';
   LowHex[1] = '\0';
   LowHex[2] = '\0';
   HighHex[0] = '\0';
   HighHex[1] = '\0';
   HighHex[2] = '\0';
   ByteOne = 0;
   ByteTwo = 0;
   ByteOne1 = "";
   ByteTwo1 = "";
   return 0;
}

int DataOutput(int i,int j,int Step,ofstream& OutputFile,ifstream& Rules,int Hex,string TotalString)
{
	int Bytes = GetByteParameters(i,j,Step);
	size_t Distance = GetSpaces(i,j,Step);
	if (Bytes == 3) {
		WriteBitFlagHex8Bit(OutputFile,Hex,TotalString);
	} else if (Bytes == 1) {
		WriteDWORD(OutputFile,Hex,TotalString);
	} else if (Bytes == 0) {
		WriteBYTE(OutputFile,Hex,TotalString);
	}

   return 0;
}

int WriteDataOutputFile(int i,int j,int Step,ofstream& Item,ofstream& Build,ofstream& Spell,ofstream& Magic,ofstream& Wizard,ofstream& Itemmake,ifstream& Rules)
{
	string TotalString = FindRulesNumber(i,j,Step,Rules);
	if (Step != 0) {
		if (i == 0) {
			DataOutput(i,j,Step,Item,Rules,Get_Hex_Offset(i,j,Step),TotalString);
		} else if (i == 1) {
			DataOutput(i,j,Step,Build,Rules,Get_Hex_Offset(i,j,Step),TotalString); 
		} else if (i == 2) {
			DataOutput(i,j,Step,Spell,Rules,Get_Hex_Offset(i,j,Step),TotalString); 
		} else if (i == 22 || i == 26 || i == 34 || i == 35) {
			DataOutput(i,j,Step,Magic,Rules,Get_Hex_Offset(i,j,Step),TotalString); 
		} else if (i == 24) {
			if (j == 0) {
				DataOutput(i,j,Step,Wizard,Rules,BookRetort_Additives[0],TotalString); 
				DataOutput(i,j,Step,Wizard,Rules,BookRetort_Additives[3],TotalString);
			} else if (j == 1) {
				DataOutput(i,j,Step,Wizard,Rules,BookRetort_Additives[1],TotalString); 
				DataOutput(i,j,Step,Wizard,Rules,BookRetort_Additives[4],TotalString);
			} else if (j == 2) {
				DataOutput(i,j,Step,Wizard,Rules,BookRetort_Additives[2],TotalString);
			}
		} 	else if (i == 25) {
			if (j == 0) {
				DataOutput(i,j,Step,Wizard,Rules,GoldMana_Additives[1],TotalString); 
				DataOutput(i,j,Step,Wizard,Rules,GoldMana_Additives[3],TotalString);
			} else if (j == 1) {
				DataOutput(i,j,Step,Wizard,Rules,GoldMana_Additives[0],TotalString); 
				DataOutput(i,j,Step,Wizard,Rules,GoldMana_Additives[2],TotalString);
			}
		} 	else if (i == 30) {
			DataOutput(i,j,Step,Itemmake,Rules,Create_Spell_Charges_Costs_Additives[1],TotalString); 
			DataOutput(i,j,Step,Wizard,Rules,Create_Spell_Charges_Costs_Additives[0],TotalString);
		} 	else if (i == 31) {
			DataOutput(i,j,Step,Itemmake,Rules,Create_Base_Costs_Additives[1] + Create_Base_Costs_Steps_Additives[Step],TotalString); 
			DataOutput(i,j,Step,Wizard,Rules,Create_Base_Costs_Additives[0] + Create_Base_Costs_Steps_Additives[Step],TotalString);
		} 	else if (i == 33) {
			if (Str2Int(TotalString) == 50) TotalString = "49707";
			if (Str2Int(TotalString) == 25) TotalString = "63697"; 
			DataOutput(i,j,Step,Wizard,Rules,Get_Hex_Offset(i,j,Step),TotalString);
		} 	else if (i == 36) {
			if (j == 11) {
				DataOutput(i,j,Step,Magic,Rules,Map_Generation_Two_Additives[j],TotalString);
				int Value = Str2Int(TotalString);
				Value += 6;
				TotalString = Int2Str(Value);
				DataOutput(i,j,Step,Magic,Rules,Map_Generation_One_Additives[j],TotalString);
			} else {
				DataOutput(i,j,Step,Magic,Rules,Get_Hex_Offset(i,j,Step),TotalString);
				DataOutput(i,j,Step,Magic,Rules,Get_Hex_Offset(i,j,Step),TotalString);
			}
		} else {
			DataOutput(i,j,Step,Wizard,Rules,Get_Hex_Offset(i,j,Step),TotalString);
		}
	}

	return 0; 
}

int WriteData(int i,int j,ofstream& Item,ofstream& Build,ofstream& Spell,ofstream& Magic,ofstream& Wizard,ofstream& Itemmake,ifstream& Rules)
{
   for (int Step = 0;Step < step_max[i];Step++) {
      WriteDataOutputFile(i,j,Step,Item,Build,Spell,Magic,Wizard,Itemmake,Rules); 
   }

	return 0; 
}

int WriteDataTableToFiles(int i,ofstream& Item,ofstream& Build,ofstream& Spell,ofstream& Magic,ofstream& Wizard,ofstream& Itemmake,ifstream& Rules)
{
   for (int j = 0; j < rec_count[i];j++) {
      WriteData(i,j,Item,Build,Spell,Magic,Wizard,Itemmake,Rules);
   }

   return 0;
}