/******************************************************************************/
/*                                                                            */
/*  GNU Phantom.Home.Console 1.00                                             */
/*  06/26/2000                                                                */
/*  Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>       */
/*                                                                            */
/*  This program is free software; you can redistribute it and/or modify it   */
/*  under the terms of the GNU General Public License as published by the     */
/*  Free Software Foundation; either version 2 of the License, or (at your    */
/*  option) any later version.                                                */
/*                                                                            */
/******************************************************************************/

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <fstream.h>
#include <time.h>
#include <ctype.h>

#define VERSION2 "1.00"
#define BASEPORT 0x378
#define Phantom_Devices "Phantom.Devices"
#define Phantom_Groups "Phantom.Groups"
#define Phantom_Out "Phantom.Home.Out"
#define Phantom_In "Phantom.Home.In"

int system(const char * string);

void parse_devices(ifstream& file_devices, bool &D1_S, bool &D2_S, bool &D3_S, bool &D4_S, bool &D5_S, bool &D6_S, bool &D7_S, bool &D8_S, string &D1_A, string &D2_A, string &D3_A, string &D4_A, string &D5_A, string &D6_A, string &D7_A, string &D8_A, bool &ef, int &returnstatus)
{
	/* PARSE_DEVICES:                                                  */
	/* This function takes the options in the Phantom.Devices file and */
	/* sucks it into data we can use.  This function, along with       */
	/* parse_groups are necessary, and need to be error checked, in    */
	/* order to make the most of this package.   As well as make it    */
	/* easier to use!                                                  */

	cout << "Reading Phantom.Devices file...";

	const char nwln = '\n';
	char x;
	int i;
	string q1, q2, q3;

	/* Open up the Phantom.Devices file */
	file_devices.open (Phantom_Devices);

	if (!file_devices.fail())
	{
	
	/* Start the process by getting the first char */
	file_devices.get (x);
	while (!file_devices.eof ())
	{
		i = 1;
		q1 = ""; q2 = ""; q3 = ""; 
		while (x != nwln)
		{
			if (x != ':')
			{
				if (i == 1) {q1 = q1 + x;}
				if (i == 2) {q2 = q2 + x;}
				if (i == 3) {q3 = q3 + x;}
				file_devices.get (x);
			}
			else
			{
				i++;
				file_devices.get (x);
			}
		}
		file_devices.get (x);

		if (q1 == "DEVICE1")
		{
			if (q2 == "Enabled")
			{
				D1_S = true;
				D1_A = q3;
			}
			else
			{
				D1_S = false;
			}
		}
		if (q1 == "DEVICE2")
		{
			if (q2 == "Enabled")
			{
				D2_S = true;
				D2_A = q3;
			}
			else
			{
				D2_S = false;
			}
		}
		if (q1 == "DEVICE3")
		{
			if (q2 == "Enabled")
			{
				D3_S = true;
				D3_A = q3;
			}
			else
			{
				D3_S = false;
			}
		}
		if (q1 == "DEVICE4")
		{
			if (q2 == "Enabled")
			{
				D4_S = true;
				D4_A = q3;
			}
			else
			{
				D4_S = false;
			}
		}
		if (q1 == "DEVICE5")
		{
			if (q2 == "Enabled")
			{
				D5_S = true;
				D5_A = q3;
			}
			else
			{
				D5_S = false;
			}
		}
		if (q1 == "DEVICE6")
		{
			if (q2 == "Enabled")
			{
				D6_S = true;
				D6_A = q3;
			}
			else
			{
				D6_S = false;
			}
		}
		if (q1 == "DEVICE7")
		{
			if (q2 == "Enabled")
			{
				D7_S = true;
				D7_A = q3;
			}
			else
			{
				D7_S = false;
			}
		}
		if (q1 == "DEVICE8")
		{
			if (q2 == "Enabled")
			{
				D8_S = true;
				D8_A = q3;
			}
			else
			{
				D8_S = false;
			}
		}
	}

	/* Close the Phantom.Devices file */
	file_devices.close ();

	cout << "Done!" << endl ;
	cout << "Type 'show devices' to get a list." << endl << endl;

	}
	else
	{
		cout << "None!" << endl ;
		cout << "FATAL ERROR:  Error reading Phantom.Devices" << endl;
		cout << endl;
		ef = true;
		returnstatus=2;
	}

}

void show_devices(bool D1_S, bool D2_S, bool D3_S, bool D4_S, bool D5_S, bool D6_S, bool D7_S, bool D8_S, string D1_A, string D2_A, string D3_A, string D4_A, string D5_A, string D6_A, string D7_A, string D8_A)
{
	/* OK.  Now let's reap the fruits of our harvest and display the */
	/* results of the parsing.                                       */
	if (D1_S == true) 
		cout << "DEVICE 1 (" << D1_A << ") is enabled." << endl;
	else
		cout << "DEVICE 1 is disabled." << endl;
	if (D2_S == true) 
		cout << "DEVICE 2 (" << D2_A << ") is enabled." << endl;
	else
		cout << "DEVICE 2 is disabled." << endl;
	if (D3_S == true) 
		cout << "DEVICE 3 (" << D3_A << ") is enabled." << endl;
	else
		cout << "DEVICE 3 is disabled." << endl;
	if (D4_S == true) 
		cout << "DEVICE 4 (" << D4_A << ") is enabled." << endl;
	else
		cout << "DEVICE 4 is disabled." << endl;
	if (D5_S == true) 
		cout << "DEVICE 5 (" << D5_A << ") is enabled." << endl;
	else
		cout << "DEVICE 5 is disabled." << endl;
	if (D6_S == true) 
		cout << "DEVICE 6 (" << D6_A << ") is enabled." << endl;
	else
		cout << "DEVICE 6 is disabled." << endl;
	if (D7_S == true) 
		cout << "DEVICE 7 (" << D7_A << ") is enabled." << endl;
	else
		cout << "DEVICE 7 is disabled." << endl;
	if (D8_S == true) 
		cout << "DEVICE 8 (" << D8_A << ") is enabled." << endl;
	else
		cout << "DEVICE 8 is disabled." << endl;
}

void parse_groups(ifstream& file_groups, string &G1_A, string &G2_A, string &G3_A, string &G4_A, string &G1_D, string &G2_D, string &G3_D, string &G4_D)
{
	/* PARSE_GROUPS:                                                    */
	/* This function reads the Phantom.Groups alias file.  Groups are   */
	/* just aliases for user defined groups of devices.  For example,   */
	/* let's say you have two lights that you want to retain individual */
	/* control over, yet you want some easy way to turn both of them on */
	/* or off at the same time.  Then you can create a group called     */
	/* 'lights' or something, and do it that easily!                    */

	cout << "Reading Phantom.Groups file...";

	const char nwln = '\n';
	char x;
	int i;
	string q1, q2, q3, q4;

	/* If someones got a screwy Phantom.Groups file, */
	/* better put some checks in...                  */
	/* In other words, guilty until proven innocent! */
	G1_A = "N/A";
	G2_A = "N/A";
	G3_A = "N/A";
	G4_A = "N/A";

	/* Open up the Phantom.Groups file */
	file_groups.open (Phantom_Groups);

	/* Only if the file's there... */
	if(!file_groups.fail())
	{

	/* Start the process by getting the first char */
	file_groups.get (x);
	while (!file_groups.eof ())
	{
		i = 1;
		q1 = ""; q2 = ""; q3 = ""; q4 = "";

		while (x != nwln)
		{
			if (x != ':')
			{
				if (i == 1) {q1 = q1 + x;}
				if (i == 2) {q2 = q2 + x;}
				if (i == 3) {q3 = q3 + x;}
				if (i == 4) {q4 = q4 + x;}
				file_groups.get (x);
			}
			else
			{
				i++;
				file_groups.get (x);
			}
		}
		file_groups.get (x);

		if (q1 == "GROUP1")
		{
			if (q2 == "Enabled")
			{
				G1_A = q3;
				G1_D = q4;
			}
			else
			{
				G1_A = "N/A";
				G1_D = "N/A";
			}
		}
		if (q1 == "GROUP2")
		{
			if (q2 == "Enabled")
			{
				G2_A = q3;
				G2_D = q4;
			}
			else
			{
				G2_A = "N/A";
				G2_D = "N/A";
			}
		}
		if (q1 == "GROUP3")
		{
			if (q2 == "Enabled")
			{
				G3_A = q3;
				G3_D = q4;
			}
			else
			{
				G3_A = "N/A";
				G3_D = "N/A";
			}
		}
		if (q1 == "GROUP4")
		{
			if (q2 == "Enabled")
			{
				G4_A = q3;
				G4_D = q4;
			}
			else
			{
				G4_A = "N/A";
				G4_D = "N/A";
			}
		}
	}

	/* Close out the Phantom.Groups file */
	file_groups.close();

	cout << "Done!" << endl;
	cout << "Type 'show groups' to get a list." << endl << endl;
	
	}
	else
	{
		cout << "None." << endl;
	}
}

void show_groups(string &G1_A, string &G2_A, string &G3_A, string &G4_A, string &G1_D, string &G2_D, string &G3_D, string &G4_D)
{
		/* OK.  Now display the results. */
		if (G1_A != "N/A")
			cout << "GROUP 1 (" << G1_A << ") contains devices (" << G1_D << ")." << endl;
		else
			cout << "GROUP 1 is disabled." << endl;
		if (G2_A != "N/A")
			cout << "GROUP 2 (" << G2_A << ") contains devices (" << G2_D << ")." << endl;
		else
			cout << "GROUP 2 is disabled." << endl;
		if (G3_A != "N/A")
			cout << "GROUP 3 (" << G3_A << ") contains devices (" << G3_D << ")." << endl;
		else
			cout << "GROUP 3 is disabled." << endl;
		if (G4_A != "N/A")
			cout << "GROUP 4 (" << G4_A << ") contains devices (" << G4_D << ")." << endl;
		else
			cout << "GROUP 4 is disabled." << endl;
}

string j_upper(string j_in)
{
	int length, counter;
	char x;

	length=j_in.length();
	
	for (counter=0; counter < length; counter++)
	{
		x=j_in.at (counter);
		j_in.replace(counter, 1, toupper(x));
	}

	return j_in;
}

string j_remove_commas(string j_in)
{
	/* I really miss the 'sed' and 'tr' unix shell commands... */

	int length, counter;
	char y;
	
	length=j_in.length();

	for (counter=0; counter < length; counter++)
	{
		y=j_in.at (counter);
		if (y==',') {j_in.replace (counter, 1, " ");};
	}

	return j_in;
}

string j_remove_periods(string j_in2)
{
	/* I really miss the 'sed' and 'tr' unix shell commands... */

	int length2, counter2;
	char z;

	length2=j_in2.length();

	for (counter2=0; counter2 < length2; counter2++)
	{
		z=j_in2.at (counter2);
		if (z=='.') {j_in2.replace (counter2, 1, " ");};
	}

	return j_in2;
}

void command_out(bool &D1, bool &D2, bool &D3, bool &D4, bool &D5, bool &D6, bool &D7, bool &D8, string D1_A, string D2_A, string D3_A, string D4_A, string D5_A, string D6_A, string D7_A, string D8_A, bool D1_S, bool D2_S, bool D3_S, bool D4_S, bool D5_S, bool D6_S, bool D7_S, bool D8_S, string G1_A, string G2_A, string G3_A, string G4_A, string G1_D, string G2_D, string G3_D, string G4_D, ofstream& file_out, char to_go_out)
{
	/* Basically, I want to make this package more modular.  Before */
	/* (i.e. Beta0.60 & below) I used to output the character for   */
	/* Homed to the file in command_parser().  However, to make the */
	/* outputting process modular I need to do that in a central    */
	/* function.  This is it.  This will make it easier to merge    */
	/* Phantom.Homed & Phantom.Home.Console to create a single-user */
	/* version (i.e. for a DOS/Win port).  So for the DOS port,     */
	/* I just basically do a transplant of the core functions of    */
	/* Phantom.Homed & put it here.                                 */

	file_out.open(Phantom_Out);
	file_out << to_go_out;
	file_out.close();
}

void command_parser(string command, bool &D1, bool &D2, bool &D3, bool &D4, bool &D5, bool &D6, bool &D7, bool &D8, string D1_A, string D2_A, string D3_A, string D4_A, string D5_A, string D6_A, string D7_A, string D8_A, bool D1_S, bool D2_S, bool D3_S, bool D4_S, bool D5_S, bool D6_S, bool D7_S, bool D8_S, string G1_A, string G2_A, string G3_A, string G4_A, string G1_D, string G2_D, string G3_D, string G4_D, ofstream& file_out, ifstream& file_in)
{
	string command2, command3, command4, command5, temp, temp2, temp4;
	char x, i;
	int temp3, counter, length;
	bool cp_ef, ok_togo, aok;

	cp_ef=false;
	ok_togo=false;
	aok=false;

	/* If command < 4 characters, a core dump occurs... don't do this! */
	if (command.length () > 4)
	{

	/* For network version, check status... */
	/* First send status request to Phantom.Homed... */
	command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '0');

	/* Second, wait for a reply */
	file_in.open(Phantom_In);
	while (file_in.fail())
	{
		file_in.open(Phantom_In);
	}
	file_in.get(i);
	if (i=='1') {D1=true;} else {D1=false;};
	file_in.get(i);
	if (i=='1') {D2=true;} else {D2=false;};
	file_in.get(i);
	if (i=='1') {D3=true;} else {D3=false;};
	file_in.get(i);
	if (i=='1') {D4=true;} else {D4=false;};
	file_in.get(i);
	if (i=='1') {D5=true;} else {D5=false;};
	file_in.get(i);
	if (i=='1') {D6=true;} else {D6=false;};
	file_in.get(i);
	if (i=='1') {D7=true;} else {D7=false;};
	file_in.get(i);
	if (i=='1') {D8=true;} else {D8=false;};
	file_in.close();
	remove(Phantom_In);

	/* ----- AUTOLIGHTING ENABLE ----- */
	/* -- (im here, im back) -- */
	command2="";
	command2.assign (command, 0, 7);
	if ((command2 == "IM HERE" || command2 == "IM BACK") && aok == false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 's');
		cout << "Disabled AUTOLIGHTING." << endl;
		aok=true;
	}
	/* -- (in) -- */
	command2="";
	command2.assign (command, 0, 2);
	if (command2 == "IN" && aok == false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 's');
		cout << "Disabled AUTOLIGHTING." << endl;
		aok=true;
	}


	/* ----- AUTOLIGHTING ENABLE ----- */
	/* -- (im leaving) -- */
	command2="";
	command2.assign (command, 0, 10);
	if (command2 == "IM LEAVING" && aok == false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'r');
		cout << "Enabled AUTOLIGHTING." << endl;
		aok=true;
	}
	/* -- (out) -- */
	command2="";
	command2.assign (command, 0, 3);
	if (command2 == "OUT" && aok == false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'r');
		cout << "Enabled AUTOLIGHTING." << endl;
		aok=true;
	}
		

	/* ----- STATUS ----- */
	command2.assign (command, 0, 6);
	if (command2 == "STATUS" || command2 == "STATUS." && aok == false)
	{
		if (D1_S == 1) {if (D1 == 1) {cout << D1_A << " is on." << endl;} else {cout << D1_A << " is off." << endl;};};
		if (D2_S == 1) {if (D2 == 1) {cout << D2_A << " is on." << endl;} else {cout << D2_A << " is off." << endl;};};
		if (D3_S == 1) {if (D3 == 1) {cout << D3_A << " is on." << endl;} else {cout << D3_A << " is off." << endl;};};
		if (D4_S == 1) {if (D4 == 1) {cout << D4_A << " is on." << endl;} else {cout << D4_A << " is off." << endl;};};
		if (D5_S == 1) {if (D5 == 1) {cout << D5_A << " is on." << endl;} else {cout << D5_A << " is off." << endl;};};
		if (D6_S == 1) {if (D6 == 1) {cout << D6_A << " is on." << endl;} else {cout << D6_A << " is off." << endl;};};
		if (D7_S == 1) {if (D7 == 1) {cout << D7_A << " is on." << endl;} else {cout << D7_A << " is off." << endl;};};
		if (D8_S == 1) {if (D8 == 1) {cout << D8_A << " is on." << endl;} else {cout << D8_A << " is off." << endl;};};
		aok=true;
	}

	if (command == "SHOW DEVICES" || command == "LIST DEVICES" || command == "DISPLAY DEVICES" && aok == false) {show_devices(D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A);aok=true;};

	if (command == "SHOW GROUPS" || command == "LIST GROUPS" || command == "DISPLAY GROUPS" && aok == false) {show_groups(G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D);aok=true;};

	/* TURN ON ALL/TURN ALL ON */
	if (command == "TURN ALL ON" || command == "TURN ON ALL" && aok==false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'p');
		cout << "Turned on all devices." << endl;
		aok=true;
	}

	/* TURN OFF ALL/TURN ALL OFF */
	if (command == "TURN ALL OFF" || command =="TURN OFF ALL" && aok==false)
	{
		command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'q');
		cout << "Turned off all devices." << endl;
		aok=true;
	}

	/* ----- TURN ON X/TURN ON THE X ----- */
	if (aok == false) 
	{

	command2.assign (command, 0, 8);
	command3.assign (command, 0, 5);
	command4.assign (command, command.length () - 3, 3);
	command5.assign (command, 0, 9);
	if (command2 == "TURN ON " || (command3 == "TURN " && command4 == " ON"))
	{
		/* 'TURN ON X'? */
		temp4="";
		temp4.assign (command, 0, 12);
		if (temp4 == "TURN ON THE " && ok_togo == false) {temp.assign (command, 12);ok_togo=true;};

		/* 'TURN ON THE X'? */
		temp4="";
		temp4.assign (command, 0, 8);
		if (temp4 == "TURN ON " && ok_togo == false) {temp.assign (command, 8); ok_togo=true;}

		/* 'TURN THE X ON'? */
		if (command5 == "TURN THE " && command4 == " ON" && ok_togo == false) {temp.assign (command, 9, command.length () - 3 - 9); ok_togo=true;};
	
		/* 'TURN X ON'? */
		if (command3 == "TURN " && command4 == " ON" && ok_togo == false) {temp.assign (command, 5, command.length () - 3 - 5); ok_togo=true;};

		/* Test to see if command matches any DEVICE 1 aliases */
		if (D1_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D1_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D1 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '1');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}
		
		/* Test to see if command matches any DEVICE 2 aliases */
		if (D2_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D2_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D2 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '2');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 3 aliases */
		if (D3_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D3_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D3 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '3');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 4 aliases */
		if (D4_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D4_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D4 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '4');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 5 aliases */
		if (D5_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D5_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D5 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '5');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 6 aliases */
		if (D6_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D6_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D6 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '6');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 7 aliases */
		if (D7_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D7_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D7 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '7');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 8 aliases */
		if (D8_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D8_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D8 == false)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '8');
					cout << "Turned on " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already on!" << endl;
				}
			}
		}

		/* Test to see if command matches any GROUP 1 aliases */
		if (G1_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G1_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'h');
				cout << "Turned on group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 2 aliases */
		if (G2_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G2_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'i');
				cout << "Turned on group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 3 aliases */
		if (G3_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G3_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'j');
				cout << "Turned on group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 4 aliases */
		if (G4_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G4_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'k');
				cout << "Turned on group " << temp << "." << endl;
			}
		}


		if (cp_ef == false) {cout << "I don't know what '" << temp << "' is." << endl;};
	aok = true;
	}

	}



	/* ----- TURN OFF X/TURN OFF THE X/TURN X OFF/TURN THE X OFF ----- */
	if (aok == false)
	{

	command2.assign (command, 0 , 9);
	command3.assign (command, 0 , 5);
	command4.assign (command, command.length () - 4 , 4);
	command5.assign (command, 0 , 9);

	ok_togo=false;

	if (command2 == "TURN OFF " || (command3 == "TURN " && command4 == " OFF"))
	{

	/* 'TURN OFF THE X'? */
	temp4="";
	temp4.assign (command, 0, 13);
	if (temp4 == "TURN OFF THE " && ok_togo == false) {temp.assign (command, 13); ok_togo=true;};

	/* 'TURN OFF X'? */
	temp4="";
	temp4.assign (command, 0, 9);
	if (temp4 == "TURN OFF " && ok_togo == false) {temp.assign (command, 9); ok_togo=true;};

	/* 'TURN THE X OFF'? */
	if (command5 == "TURN THE " && command4 == " OFF" && ok_togo == false) {temp.assign (command, 9, command.length () - 4 - 9); ok_togo=true;};


	/* 'TURN X OFF'? */
	if (command3 == "TURN " && command4 == " OFF" && ok_togo == false) {temp.assign (command, 5, command.length () - 4 - 5); ok_togo=true;};


		/* Test to see if command matches any DEVICE 1 aliases */
		if (D1_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D1_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D1 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '1');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}
		
		/* Test to see if command matches any DEVICE 2 aliases */
		if (D2_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D2_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D2 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '2');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 3 aliases */
		if (D3_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D3_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D3 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '3');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 4 aliases */
		if (D4_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D4_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D4 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '4');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 5 aliases */
		if (D5_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D5_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D5 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '5');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 6 aliases */
		if (D6_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D6_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D6 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '6');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 7 aliases */
		if (D7_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D7_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D7 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '7');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}

		/* Test to see if command matches any DEVICE 8 aliases */
		if (D8_S == true && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(D8_A));
			if (temp2.find (temp) < temp2.length ()) 
			{
				cp_ef=true;
				if (D8 == true)
				{
					command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, '8');
					cout << "Turned off " << temp << "." << endl;
				}
				else
				{
					cout << temp << " is already off!" << endl;
				}
			}
		}


		/* Test to see if command matches any GROUP 1 aliases */
		if (G1_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G1_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'l');
				cout << "Turned off group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 2 aliases */
		if (G2_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G2_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'm');
				cout << "Turned off group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 3 aliases */
		if (G3_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G3_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'n');
				cout << "Turned off group " << temp << "." << endl;
			}
		}

		/* Test to see if command matches any GROUP 4 aliases */
		if (G4_A != "N/A" && cp_ef == false)
		{
			temp2=j_upper(j_remove_commas(G4_A));
			if (temp2.find (temp) < temp2.length ())
			{
				cp_ef=true;
				command_out(D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A,  D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, 'o');
				cout << "Turned off group " << temp << "." << endl;
			}
		}




		if (cp_ef == false) {cout << "I don't know what '" << temp << "' is." << endl;};
	aok = true;
	}
	}
}


}

int main(int argc, char *argv[])
{
	/* Declare the 8 Device variables */
	bool D1, D2, D3, D4, D5, D6, D7, D8;	
	/* Declare the 8 Device Status variables as booleans */
	bool D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S;
	/* Declare the 8 Device Alias variables as strings */
	string D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A;
	/* Declare the 4 Group Alias variables as strings */
	string G1_A, G2_A, G3_A, G4_A;
	/* Declare the 4 Group Device variables as strings */
	string G1_D, G2_D, G3_D, G4_D;
	/* Declare file_devices as input file stream */
	ifstream file_devices;
	/* Declare file_groups as input file stream */
	ifstream file_groups;
	/* Declare ef as boolean exit flag */
	bool ef;
	/* Declare command as string */
	string command;
	/* Declare file_out as an Output file stream */
	ofstream file_out;
	/* Declare file_in as an Input file stream */
	ifstream file_in;
	/* Declare homedir as char */
	char homedir[128] = "";
	/* Declare tempchar as char */
	char tempchar;
	/* Declare counter as int */
	int counter;
	/* Declare temp as string */
	string temp;
	/* Declare returnstatus as int */
	int returnstatus;

	/* Initialize variables */
	D1=0; D2=0; D3=0; D4=0; D5=0; D6=0; D7=0; D8=0;

	/* Set the exit flag to false */
	ef = false;
	returnstatus=0;

	/* ---------- PARSE COMMAND LINE --------- */
	for (counter = 1; counter < argc; counter++)
	{
		temp=argv[counter];

		if (temp=="--version")
		{
			cout << "GNU Phantom.Home.Console " << VERSION2 << endl;
			cout << "Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>" << endl;
			cout << "GNU Phantom.Home.Console comes with NO WARRANTY," << endl;
			cout << "to the extent permitted by law." << endl;
			cout << "You may redistribute copies of GNU Phantom.Home.Console" << endl;
			cout << "under the terms of the GNU General Public License" << endl;
			cout << "For more information about these matters," << endl;
			cout << "see the file named COPYING." << endl << endl;
			ef=true;
			returnstatus=0;
		}

		if (temp=="--help")
		{
			cout << "GNU Phantom.Home.Console " << VERSION2 << endl;
			cout << "Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>" << endl << endl;
			cout << "Arguments: " << endl;	
			cout << "--help        To get this list" << endl;
			cout << "--version     To get the version" << endl;
			cout << endl;
			ef=true;
			returnstatus=0;
		}
	}
	/* ---------- PARSE COMMAND LINE --------- */
	
	if (ef==false)
	{

	/* Initialize the display */
	cout << "\033[2J" << "\033[1;1H";
	cout << "Phantom Computer Controlled Home Automation System" << endl << endl;
	cout << "Copyright (C) 1999, 2000 by Joe Thielen <jthielen@accesstoledo.com>" << endl << endl;
	cout << "This program is free software; you can redistribute it and/or modify it" << endl;
	cout << "under the terms of the GNU General Public License as published by the" << endl;
	cout << "Free Software Foundation; either version 2 of the License or, (at your" << endl;
	cout << "option) any later version." << endl;
	cout << "See the file COPYING for more details." << endl;
	cout << "This software comes with NO WARRANTY of any kind." << endl << endl;

	cout << "GNU Phantom.Home.Console" << endl;
	cout << "Version: " << VERSION2 << endl << endl;

	}

	if (ef == false)
	{
		parse_devices(file_devices, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A, ef, returnstatus);
	}

	if (ef == false)
	{
		parse_groups(file_groups, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D);
	}

	while (ef == false)
	{
		/* ----------------- */
		/* MAIN ROUTINE LOOP */
		/* -------vvv------- */

		/* First, issue a prompt, and wait for the users command! */
		cout << endl << "What can I do for you?" << endl << ": ";
		getline (cin, command, '\n');

		if (j_upper(command)=="EXIT" || j_upper(command)=="QUIT") {ef = true;} else {command_parser(j_upper(command), D1, D2, D3, D4, D5, D6, D7, D8, D1_A, D2_A, D3_A, D4_A, D5_A, D6_A, D7_A, D8_A, D1_S, D2_S, D3_S, D4_S, D5_S, D6_S, D7_S, D8_S, G1_A, G2_A, G3_A, G4_A, G1_D, G2_D, G3_D, G4_D, file_out, file_in);};

		/* -------^^^----------- */
		/* END MAIN ROUTINE LOOP */
		/* --------------------- */
	}

	cout << endl << "Exiting GNU Phantom.Home.Console " << VERSION2 << "!" << endl <<endl;

	return returnstatus;
}
