/*
 *            Copyright (c) 1998-2000 by NETsilicon Inc.
 *
 *  This software is copyrighted by and is the sole property of 
 *  NETsilicon.  All rights, title, ownership, or other interests
 *  in the software remain the property of NETsilicon.  This
 *  software may only be used in accordance with the corresponding
 *  license agreement.  Any unauthorized use, duplication, transmission,  
 *  distribution, or disclosure of this software is expressly forbidden.
 *
 *  This Copyright notice may not be removed or modified without prior
 *  written consent of NETsilicon.
 *
 *  NETsilicon, reserves the right to modify this software
 *  without notice.
 *
 *  NETsilicon
 *  411 Waverley Oaks Road                  USA 781.647.1234
 *  Suite 227                               http://www.netsilicon.com
 *  Waltham, MA 02452                       AmericaSales@netsilicon.com
 *
 *************************************************************************
 *
 *     Module Name: root.cxx
 *         Version: 1.00
 *   Original Date: 08/23/99	
 *          Author: Julia Rakhvalska
 *        Language: Ansi C++
 * Compile Options: 
 * Compile defines: 
 *       Libraries: 
 *    Link Options: 
 *
 *    Entry Points: applicationStart(), applicationTcpDown()
 *
 * Description.
 * =======================================================================
 * applicationStart() is the entry point for user applications.  This
 * This function will be called after the kernel has started and the
 * TCP/IP stack has loaded.  applicationTcpDown() is called periodically
 * after the kernel has started while the system is waiting for the
 * TCP/IP stack to start.  
 *          
 * This is a C++ example application. 
 *
 * applicationTcpDown() callback uses the global object PrintApplicationDown app_down 
 * which prints application name, and then '.' every second, while the application starts.
 * 
 * applicationStart() starts 4 UDP echo threads. UDP echo thread function UdpEchoThread()
 * uses thread argument as the local port number. UdpEchoThread() a socket using local 
 * CSocket so object and uses it to send back received datagrams
 *
 * Edit Date/Ver   Edit Description
 * ==============  ===================================================
 *
 */
   
#ifndef NETOS_GNU_TOOLS
#include <stdio.h>
#else
#include <iostream>
#endif
#include <stdlib.h>
#include "appdown.h"
//#include "CSocket.h"


#include "animalsBase.h"
#include "mammal.h"
#include "reptile.h"
#include "snake.h" 
 
#include <tx_api.h>
#include "appconf.h"
#include <netoserr.h>

#ifdef NETOS_GNU_TOOLS
	using namespace std;
#endif




/*
 * Set this to 1 to run the system POST tests during startup.
 */
const int APP_POST = 0;

/*
 * Set this to 1 to run the manufacturing burn in tests.
 */
int APP_BURN_IN_TEST = 0;

extern "C"
{
void makeAnimals(); 
}

/*
 * Global C++ object to determine startup time
 */
ApplicationDownCnt app_down;

extern "C"
{
animalBase::animalBase()
{
	cout << "creating a default animal" << endl;
	this->isSleeping = awake;
	this->numChildren = 0;
	this->whatEats = omnivore;
	this->whereAreWe.x = 0;
	this->whereAreWe.y = 0;
	this->whenActive = notNocternal;
}
}


extern "C"
{
animalBase::animalBase(int isNocternal, int whatEats)
{
	cout << "creating an animal with inputs" << endl;
	this->whatEats = whatEats;
	this->isSleeping = awake;
	this->numChildren = 0;
	this->whereAreWe.x = 0;
	this->whereAreWe.y = 0;
	this->whenActive = nocternal;
}
}

extern "C"
{
animalBase::~animalBase()
{
	cout << "deleting an animal" << endl;
}
}


extern "C"
{
int animalBase::move(int x, int y)
{
	int status = moveFailure;

	if(this->areWeSleeping() == asleep)
	{
		cout << "animal can't move, sleeping" << endl;
	}
	else
	{
	    cout << "moving animal " << x << " by " << y << endl; 
	    this->whereAreWe.x += x;
	    this->whereAreWe.y += y;
		status = moveSuccess;
	}
	return status;
}
}

extern "C"
{
int animalBase::goToSleep()
{
	cout << "animal going to sleep" << endl;
	this->isSleeping = asleep;
	return sleepSuccess;
}
}

extern "C"
{
int animalBase::areWeSleeping()
{
	return this->isSleeping;
}
}

extern "C"
{
int animalBase::eat()
{
	int status = eatFailure;

	if(this->areWeSleeping() == asleep)
	{
		cout << "animal can't eat, asleep" <<endl;
		status = eatFailure;
	}
	else
	{
		cout << "animal ate something or somebody" << endl;
		status = eatSuccess;
	}
	return status;
}
}



extern "C"
{
void animalBase::print()
{
	cout << "animal eats- " << this->whatEats << " whenactive- " << this->whenActive 
		<< " is sleeping- " 
		<< this->isSleeping << " num children- " << this->numChildren 
		<< " where are we- " 
		<< this->whereAreWe.x << " X " << this->whereAreWe.y << endl;
    //cout << "in animal print " << endl;
}
}

extern "C"
{
void animalBase::incrementChildren(int numNewChildern)
{
	this->numChildren += numNewChildern;
}
}


extern "C"
{
int animalBase::procreate(int numNewChildren)
{
	if(this->areWeSleeping() == asleep)
	{
		cout << "animal can't procreate...sleeping " << endl;
		return procreateFailure;
	}
	else
	{
		cout << " an animal procreated " << numNewChildren << endl;
		this->numChildren += numNewChildren;
		return procreateSuccess;
	}
}
}


extern "C"
{
void animalBase::wakeUp()
{
	this->isSleeping = awake;
	cout << " an animal woke up" << endl;
}
}


extern "C"
{
int animalBase::checkSleepState()
{
	return(this->areWeSleeping());
}
}






/*
 *
 *  Function: void applicationTcpDown (void)
 *
 *  Description:
 *
 *      This routine will be called by the NET+OS root thread once every 
 *      clock tick while it is waiting for the TCP/IP stack to come up.  
 *      
 *      This routone is called to print the application name and then 
 *      to print the '.' every second.
 *      
 *      This function will not be called once the stack has started.
 *
 *      This function uses the global C++ object PrintApplicationDown app_down.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */


extern "C"
void applicationTcpDown (void)
{

  /*
   * Count number  of seconds.
   */
  app_down.Update();
}



/*
 *
 *  Function: void applicationStart (void)
 *
 *  Description:
 *
 *      This routine is responsible for starting the user application.  It should 
 *      create any threads or other resources the application needs.
 *
 *      ThreadX, the NET+OS device drivers, and the TCP/IP stack will be running
 *      when this function is called.
 *
 *      This function uses global C++ object: 
 *              PrintApplicationDown app_down.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

extern "C"
void applicationStart (void)

{
    char *app_name;

    /*
     * Print how long it took to start
     */ 
 
     
     app_down.Name(app_name);

#ifndef NETOS_GNU_TOOLS
     printf("\nApplication %s started in %d secs\n\n", app_name, (int)app_down);
#else
	 cout << "\nApplication "<< app_name << " started in " << (int)app_down << "secs" <<endl<<endl;
#endif
     delete [] app_name;


	printf("Welcome to animal world\n");
	makeAnimals();


    tx_thread_suspend(tx_thread_identify());

}


extern "C"
{
void makeAnimals()
{
	animalBase ab;
	animalBase bc(notNocternal, vegitarian);
	mammalBase mb;
	mammalBase mc(notNocternal, vegitarian, 1);
	reptileBase ra;
	reptileBase rb(nocternal, carnivor, poisonous, canNotChangeColors);
	reptileBase rc(nocternal, carnivor, poisonous, canNotChangeColors);
	reptileBase rd(nocternal, carnivor, poisonous, canNotChangeColors);
	reptileBase re(nocternal, carnivor, poisonous, canNotChangeColors);
	reptileBase rf(nocternal, carnivor, poisonous, canNotChangeColors);
	reptileBase rg(nocternal, carnivor, poisonous, canNotChangeColors);
	snakeBase sa;
	snakeBase sb(notNocternal, vegitarian, notPoisonous, canNotChangeColors,
		snakeTypeGater, isNotAmphibious);
	snakeBase sc(notNocternal, vegitarian, notPoisonous, canNotChangeColors,
		snakeTypeGater, isNotAmphibious);
	snakeBase sd(notNocternal, vegitarian, notPoisonous, canNotChangeColors,
		snakeTypeGater, isNotAmphibious);
	snakeBase se(notNocternal, vegitarian, notPoisonous, canNotChangeColors,
		snakeTypeGater, isNotAmphibious);
	snakeBase sf(notNocternal, vegitarian, notPoisonous, canNotChangeColors,
		snakeTypeGater, isNotAmphibious);



    cout << "animal--------------" << endl;
	ab.move(10,10);
	ab.procreate(5);
	ab.print();
    cout << "animal--------------" << endl;
	bc.move(20,20);
	bc.procreate(6);
	bc.print();
    cout << "mammal--------------" << endl;
	mb.procreate(10);
	mb.eat();
	mb.move(25,30);
	mb.print();
    cout << "mammal--------------" << endl;
	mc.move(20, 40);
	mc.goToSleep();
	mc.eat();
	mc.procreate(8);
	mc.wakeUp();
	mc.eat();
	mc.procreate(8);
	mc.print();
    cout << "reptile--------------" << endl;
	ra.move(12,15);
	ra.attack();
	ra.eat();
	ra.procreate(15);
	ra.print();
    cout << "reptile--------------" << endl;
	rb.move(25,32);
	rb.goToSleep();
	rb.eat();
	rb.procreate(35);
	rb.wakeUp();
	rb.attack();
	rb.procreate(35);
	rb.print();
    cout << "reptile--------------" << endl;
	rc.move(25,32);
	rc.goToSleep();
	rc.eat();
	rc.procreate(35);
	rc.wakeUp();
	rc.attack();
	rc.procreate(35);
	rc.print();
    cout << "reptile--------------" << endl;
	rd.move(25,32);
	rd.goToSleep();
	rd.eat();
	rd.procreate(35);
	rd.wakeUp();
	rd.attack();
	rd.procreate(35);
	rd.print();
    cout << "reptile--------------" << endl;
	re.move(25,32);
	re.goToSleep();
	re.eat();
	re.procreate(35);
	re.wakeUp();
	re.attack();
	re.procreate(35);
	re.print();
    cout << "reptile--------------" << endl;
	rf.move(25,32);
	rf.goToSleep();
	rf.eat();
	rf.procreate(35);
	rf.wakeUp();
	rf.attack();
	rf.procreate(35);
	rf.print();
    cout << "reptile--------------" << endl;
	rg.move(25,32);
	rg.goToSleep();
	rg.eat();
	rg.procreate(35);
	rg.wakeUp();
	rg.attack();
	rg.procreate(35);
	rg.print();
    cout << "snake--------------" << endl;
	sa.slither(37,45);
	sa.eat();
	sa.procreate(34);
	sa.print();
    cout << "snake--------------" << endl;
	sb.move(27,34);
	sb.goToSleep();
	sb.procreate(37);
	sb.move(1,1);
	sb.wakeUp();
	sb.procreate(37);
	sb.move(29,38);
	sb.eat();
	sb.print();

}
}



