/*------------------------------------------------------------------------------
Description: Precinct Class for Detail Scheduler
Author: Chris Huyler, Tim Cross
Language: C++
Name: Precinct.h
Date: April 3, 2000
------------------------------------------------------------------------------*/
#include <fstream.h>
#include "Officer.h"
#include "Olist.h"

class Precinct
{
	public:
   	Precinct();                  		 // NULL constructor
      void Load();                      // Load database
      void Save();                      // Save database
      void addspace(char s[]);          // add spaces to char array
      void removespace(char s[]);       // remove spaces from char array

      void Add_Officer();               // Create a new officer
      void Remove_Officer();            // remove an officer
      Officer* Find_Officer();			 // prints olist for user to select officer

      void Add_Detail();                // create a detail
      void Assign_Detail();				 // assign a previously created detail
      void Unassign_Detail();           // unassign a detail from an officer
      bool Remove_Detail();             // remove a detail completely

      void List_Details();       		 // list all details and the officers assigned to them
      void List_Shifts();               // list all shifts and the officers assigned to them
      void List_Officers();             // list all the officers in the precinct

   private:
      void Assign_Detail(Shift *s);     // assign a detail to an officer
      Officer* Find_Officer(string N);  // return an officer by inputing name
      Officer* Find_Available_Officer(Shift *s); /* return an officer from a list of
      														    non-conflicting officers  */
		void Print_NoOfficers();			 // prints to screen when officer list is empty
      Olist<Officer*> Officers;         /* list of officers: when an officer is assigned
   											       a detail he is removed and reinserted at the bottom */
      Shift *unassigned[20];			    // used to hold unassigned shifts already created
      int uCounter;                     // keeps track of unassigned shifts
      bool loaded;                      // boolean to tell whether database has been loaded yet
};


Precinct::Precinct()
{
	uCounter = -1;
   loaded = false;
}


void Precinct::Load()
{
if(!loaded)				// database can only be loaded once
{
   cout << "\n\n\n\nLoading\n";
	loaded = true;
   char type;        // type of data being loaded O=officer, R=regular, shift D=detail
// temporary storage

   Officer *O;
   	char Name[30];
      int	BadgeNum;
      char PhoneNum[14];
      char AltPhoneNum[14];
   DetailShift *D;
   	int Day;
      int Start;
      int End;
      char Location[25];
      char Employer[25];
   RegularShift *R;
   	char Description[25];
      int CarNum;

	ifstream Ofile("database.txt");
   if(!Ofile.eof())
   {
   	Ofile >> type;
      while((type == 'O') && !Ofile.eof())       // loop for multiple officers
      {
         cout << "."; //sleep(1);
      	Ofile >> Name >> BadgeNum >> PhoneNum >> AltPhoneNum;  // input
         addspace(Name);                         // replace '_' with ' '
         addspace(PhoneNum);
         addspace(AltPhoneNum);
         O = new Officer(Name,BadgeNum,PhoneNum,AltPhoneNum);  // create officer
         Officers.insert(O);                                   // put in list
         Ofile >> type;
         while((type != 'O') && !Ofile.eof())                  // loop for shifts
         {
            cout << ".";//sleep(1);
         	if(type == 'D')
            {
            	Ofile >> Day >> Start >> End >> Location >> Employer;
               addspace(Location);
               addspace(Employer);
               D = new DetailShift(Day,Start,End,Location,Employer);
               O->Add_Shift(D);
            }
            if(type == 'R')
            {
            	Ofile >> Day >> Start >> End >> Description >> CarNum;
               addspace(Description);
               R = new RegularShift(Day,Start,End,Description,CarNum);
               O->Add_Shift(R);
            }
            Ofile >> type;
         }
      }
   }
   Ofile.close();
}
}

void Precinct::Save()
{
	char type;
// temporary storage
   Officer *O;
   	char Name[25];
      int	BadgeNum;
      char PhoneNum[14];
      char AltPhoneNum[14];
   Shift *S;
   	int Day;
      int Start;
      int End;
      char Location[25];
      char Employer[25];
   	char Description[25];
      int CarNum;

   ofstream Ofile("database.txt");
	Officers.setIterator();
   while(Officers.more())
	{
   	O = Officers.next();
      O->Set_Iterator();
      type = 'O';
      strcpy(Name,O->Get_Name());                removespace(Name);
      BadgeNum = O->Get_BadgeNum();
      strcpy(PhoneNum,O->Get_PhoneNum());        removespace(PhoneNum);
      strcpy(AltPhoneNum,O->Get_AltPhoneNum());  removespace(AltPhoneNum);
      Ofile << type <<' '<< Name <<' '<< BadgeNum <<' '
      		<< PhoneNum <<' '<< AltPhoneNum <<' '<< endl;
      S = O->Return_Next_Shift();
      while(S != NULL)     // get each shift and save in memory
      {
      	Day = S->Get_Day();
         Start = S->Get_StartTime();
         End = S->Get_EndTime();
         if(S->Identify() != "RegularShift")
         {
         	type = 'D';
            strcpy(Location,S->Get_Location());	removespace(Location);
            strcpy(Employer,S->Get_Employer()); removespace(Employer);
            Ofile << type <<' '<< Day <<' '<< Start <<' '<< End <<' '
            		<< Location <<' '<< Employer << endl;
         }
         else
         {
            type = 'R';
            strcpy(Description,S->Get_Description()); removespace(Description);
            CarNum = S->Get_CarNum();
            Ofile << type <<' '<< Day <<' '<< Start <<' '<< End <<' '
            		<< Description <<' '<< CarNum << endl;
         }
         S = O->Return_Next_Shift();
      }

	}
}
void Precinct::addspace(char s[])
{
   int index;
   char *space;
	space = strchr(s,'_');
   while(space)
   {
      index = space - s;
   	s[index] = ' ';
      space = strchr(s,'_');
	}
}
void Precinct::removespace(char s[])
{
	int index;
   char *space;
	space = strchr(s,' ');
   while(space)
   {
      index = space - s;
   	s[index] = '_';
      space = strchr(s,' ');
   }
}


void Precinct::Add_Officer()
{
  	Officer *O = new Officer;
   O->Set_Init_Officer();
   Officers.insert(O);
}


void Precinct::Remove_Officer()
{
   char *N;
   textcolor(WHITE);
	cprintf("\nEnter the Officer's name: ");
   gets(N);
   Officer *O = Find_Officer(N);
   O->Print();
   textcolor(WHITE);
   cprintf("\nRemove this officer? \n");
   plist pl(2);
   pl.insert(" Yes ");
   pl.insert(" No  ");
   if(pl.printList() == " Yes ")
      if(Officers.remove(O))
      {
         cout << endl;
      	clreol();
      	cout << "\t\t\tOFFICER REMOVED";
         sleep(2);
      }
}


Officer* Precinct::Find_Officer()
{
	int num = 0;
	Officers.setIterator();
   plist pl(50);
   while(Officers.more())     // insert officers into list one at a time
   {
      pl.insert(Officers.next()->Get_Name());
      num++;
   }
   if(num == 0)
   {
		Print_NoOfficers();
      return(NULL);
   }
   else
   {                            // print the list and get users choice
   	clrscr();
   	textcolor(WHITE);
   	cprintf("\nChoose an officer from this list - \n");
   	return(Find_Officer(pl.printList()));
   }
}


Officer* Precinct::Find_Officer(string N)
{
   bool found = false;
   Officer *O;
   Officers.setIterator();
   while(!found && Officers.more())
   {
   	O = Officers.next();
      if(O->Get_Name() == N)
      	found = true;
   }
   return(O);
}


Officer* Precinct::Find_Available_Officer(Shift *s)
{
   int num = 0;
   Officer *O;
   plist pl(50);
   Officers.setIterator();
   while(Officers.more())
   {
   	O = Officers.next();
      if(!O->Conflict(s))   // add officers with no other conflicting shifts to list
      {
      	pl.insert(O->Get_Name());
         num++;
      }
   }
   if(num == 0)
   {
		Print_NoOfficers();
      return(NULL);
   }
   else
   {                       // print list
   	clrscr();
   	textcolor(WHITE);
   	cprintf("\nChoose an officer from this list of available officers - \n");
   	return(Find_Officer(pl.printList()));
   }
}


void Precinct::Add_Detail()
{
   DetailShift *D = new DetailShift;
   uCounter++;
   unassigned[uCounter] = D;

   D->Set_Init_Detail();    // create a new detail
   textcolor(WHITE);
	cprintf("\nAssign this Detail now?\n");
   plist pl(2);
   pl.insert(" Yes ");
   pl.insert(" No  ");
   if(pl.printList() == " Yes ")
   	Assign_Detail(D);
}


void Precinct::Assign_Detail()
{
   if(uCounter != -1)
   {
		Assign_Detail(unassigned[uCounter]);
   }
}


void Precinct::Assign_Detail(Shift *s)
{
   bool assigned = false;
   string ans;
   int ans2;
   plist assign(4);
   assign.insert("1.      Officer accepts shift      ");
   assign.insert("2.      Officer declines shift     ");
   assign.insert("3.      Select a different officer ");
   assign.insert("4.      Assign shift later         ");
   while(!assigned)
   {
		Officer *O = Find_Available_Officer(s);
      clrscr();
      O->Print();
      s->Print();
      textcolor(WHITE);
      cprintf("\nPlease contact officer before assigning shift.");
      cprintf("\n\rThen choose one of the following options -");

      ans = assign.printList();
      ans2 = (int) ans[0] - 48;
      switch(ans2)
      {
      	case 1:
				if (O != NULL)
   			{
      			Officers.rotate(O);
   				O->Add_Shift(s);
      			uCounter--;
   			}
            assigned = true;
            break;
         case 2:
         	Officers.rotate(O);
            break;
         case 4:
         	assigned = true;
            break;
		}
	}
}


void Precinct::Unassign_Detail()  // not finished
{
	textcolor(YELLOW);
   cprintf("\nEnter the date of the Detail you wish to remove\r\n");
   textcolor(LIGHTGRAY);
   DayConverter dc;
   int day = dc.create_day();
   char *employer;
   cprintf("\nEnter the Employer: ");
   gets(employer);

   Officer *O;
   Officers.setIterator();
   while(Officers.more())
   {
   	O = Officers.next();
   }
}


void Precinct::List_Officers()
{
	clrscr();
   Officers.setIterator();
   while(Officers.more())
   {
      Officers.next()->Print();
      textcolor(WHITE);
      cprintf("\nPress SPACE to continue. . .\r\n");
      getch();
   }
   cprintf("\nEnd of List\n");
   textcolor(LIGHTGRAY);
   sleep(1);
}


void Precinct::List_Details()
{
   Officer *O;
   Officers.setIterator();
   while(Officers.more())
   {
   	O = Officers.next();
      cout << endl << O->Get_Name() << endl;
      O->List_Details();
      textcolor(WHITE);
      cprintf("\r\nPress SPACE to continue. . .\r\n");
      textcolor(LIGHTGRAY);
      getch();
   }
}


void Precinct::Print_NoOfficers()
{
	gotoxy(1,wherey());
   clreol();
   textcolor(RED+BLINK);
   cprintf("No Available Officers!");
   sleep(1);
   textcolor(LIGHTGRAY);
}

