#include "stdafx.h"
#include "hamster.h"

#pragma comment(lib, "hamster")

void example01(void) // simple movement
{
	Hamster* robot = new Hamster();

	// move forward
	robot->write(Hamster::LEFT_WHEEL, 50);
	robot->write(Hamster::RIGHT_WHEEL, 50);
	Hamster::wait(500);

	// move backward
	robot->write(Hamster::LEFT_WHEEL, -50);
	robot->write(Hamster::RIGHT_WHEEL, -50);
	Hamster::wait(500);

	// stop
	robot->write(Hamster::LEFT_WHEEL, 0);
	robot->write(Hamster::RIGHT_WHEEL, 0);

	// don't forget to delete
	delete robot;
}

void example02(void) // acceleration
{
	Hamster* robot = new Hamster();

	// acceleration
	for(int i = 0; i < 50; ++i)
	{
		robot->write(Hamster::LEFT_WHEEL, i);
		robot->write(Hamster::RIGHT_WHEEL, i);
		Hamster::wait(20);
	}

	Hamster::wait(500);

	// deceleration
	for(int i = 50; i >= 0; --i)
	{
		robot->write(Hamster::LEFT_WHEEL, i);
		robot->write(Hamster::RIGHT_WHEEL, i);
		Hamster::wait(20);
	}

	// don't forget to delete
	delete robot;
}

void example03(void) // led
{
	Hamster* robot = new Hamster();

	robot->write(Hamster::LEFT_LED, Hamster::LED_RED);
	robot->write(Hamster::RIGHT_LED, Hamster::LED_GREEN);
	Hamster::wait(1000);

	robot->write(Hamster::LEFT_LED, Hamster::LED_OFF);
	robot->write(Hamster::RIGHT_LED, Hamster::LED_OFF);

	// don't forget to delete
	delete robot;
}

void example04(void) // basic movement
{
	Hamster* robot = new Hamster();

	for(int i = 0; i < 10; ++i)
	{
		robot->write(Hamster::LEFT_WHEEL, 50);
		robot->write(Hamster::RIGHT_WHEEL, 50);
		Hamster::wait(500);
			
		robot->write(Hamster::LEFT_WHEEL, -50);
		robot->write(Hamster::RIGHT_WHEEL, -50);
		Hamster::wait(500);
			
		robot->write(Hamster::LEFT_WHEEL, -50);
		robot->write(Hamster::RIGHT_WHEEL, 50);
		Hamster::wait(500);
	}

	delete robot;
}

void example05(void) // staggering walk
{
	Hamster* robot = new Hamster();

	int count = 10;
	int accX;
	while(count > 0)
	{
		robot->write(Hamster::LEFT_WHEEL, -100);
		robot->write(Hamster::RIGHT_WHEEL, -100);
		accX = robot->read(Hamster::ACCELERATION);
		if(accX > 2000 || accX < -2000)
		{
			robot->write(Hamster::LEFT_WHEEL, 100);
			robot->write(Hamster::RIGHT_WHEEL, 100);
			Hamster::wait(250);
				
			robot->write(Hamster::LEFT_WHEEL, -50);
			robot->write(Hamster::RIGHT_WHEEL, 50);
			Hamster::wait(500);

			--count;
		}
	}

	delete robot;
}

void example06(void) // siren
{
	Hamster* robot = new Hamster();

	int count = 0, buzzer;
	for(int i = 0; i < 200; ++i)
	{
		buzzer = count + 500;
		count += 10;
		if(count > 200) count = 0;
		robot->write(Hamster::BUZZER, buzzer);
		Hamster::wait(20);
	}

	delete robot;
}

void example07(void) // theremin sound
{
	class ThereminExecutable : public Executable
	{
	private:
		double note;

	public:
		void onExecute(Robot* robot)
		{
			int proximity = robot->read(Hamster::LEFT_PROXIMITY);
			if(proximity < 10) proximity = 0;
			note = (note * 9 + proximity) / 10;
			robot->write(Hamster::NOTE, (int)note);
		}
	};

	Hamster* robot = new Hamster();
	Executable* executable = new ThereminExecutable();
	robot->setExecutable(executable);

	// 10 seconds
	Hamster::wait(10000);

	delete robot;
	delete executable;
}

void example08(void) // simple hand follower
{
	class HandExecutable : public Executable
	{
	public:
		void onExecute(Robot* robot)
		{
			int leftProximity = robot->read(Hamster::LEFT_PROXIMITY);
			int rightProximity = robot->read(Hamster::RIGHT_PROXIMITY);

			// left wheel
			if(leftProximity > 15)
				robot->write(Hamster::LEFT_WHEEL, (40 - leftProximity) * 4);
			else
				robot->write(Hamster::LEFT_WHEEL, 0);

			// right wheel
			if(rightProximity > 15)
				robot->write(Hamster::RIGHT_WHEEL, (40 - rightProximity) * 4);
			else
				robot->write(Hamster::RIGHT_WHEEL, 0);
		}
	};

	Hamster* robot = new Hamster();
	Executable* executable = new HandExecutable();
	robot->setExecutable(executable);

	// 10 seconds
	Hamster::wait(10000);

	delete robot;
	delete executable;
}

void example09(void) // dual theremin sound
{
	class ThereminExecutable : public Executable
	{
	private:
		double note;

	public:
		void onExecute(Robot* robot)
		{
			int proximity = robot->read(Hamster::LEFT_PROXIMITY);
			if(proximity < 10) proximity = 0;
			note = (note * 9 + proximity) / 10;
			robot->write(Hamster::NOTE, (int)note);
		}
	};

	Hamster* hamster1 = new Hamster();
	Hamster* hamster2 = new Hamster();
	Executable* executable1 = new ThereminExecutable();
	Executable* executable2 = new ThereminExecutable();

	hamster1->setExecutable(executable1);
	hamster2->setExecutable(executable2);

	// 10 seconds
	Hamster::wait(10000);

	delete hamster1;
	delete hamster2;
	delete executable1;
	delete executable2;
}

void example10(void) // mutiple basic movement
{
	int NUM_ROBOTS = 4;
	Hamster** robots = new Hamster*[NUM_ROBOTS];

	for(int i = 0; i < NUM_ROBOTS; ++i)
		robots[i] = new Hamster();

	for(int i = 0; i < 10; ++i)
	{
		for(int i = 0; i < NUM_ROBOTS; ++i)
		{
			robots[i]->write(Hamster::LEFT_WHEEL, 50);
			robots[i]->write(Hamster::RIGHT_WHEEL, 50);
		}
		Hamster::wait(500);

		for(int i = 0; i < NUM_ROBOTS; ++i)
		{
			robots[i]->write(Hamster::LEFT_WHEEL, -50);
			robots[i]->write(Hamster::RIGHT_WHEEL, -50);
		}
		Hamster::wait(500);

		for(int i = 0; i < NUM_ROBOTS; ++i)
		{
			robots[i]->write(Hamster::LEFT_WHEEL, -50);
			robots[i]->write(Hamster::RIGHT_WHEEL, 50);
		}
		Hamster::wait(500);
	}

	for(int i = 0; i < NUM_ROBOTS; ++i)
		delete robots[i];
	delete [] robots;
}

void example11(void) // multiple hand follower
{
	class HandExecutable : public Executable
	{
	public:
		void onExecute(Robot* robot)
		{
			int leftProximity = robot->read(Hamster::LEFT_PROXIMITY);
			int rightProximity = robot->read(Hamster::RIGHT_PROXIMITY);

			// left wheel
			if(leftProximity > 15)
				robot->write(Hamster::LEFT_WHEEL, (40 - leftProximity) * 4);
			else
				robot->write(Hamster::LEFT_WHEEL, 0);

			// right wheel
			if(rightProximity > 15)
				robot->write(Hamster::RIGHT_WHEEL, (40 - rightProximity) * 4);
			else
				robot->write(Hamster::RIGHT_WHEEL, 0);
		}
	};

	int NUM_ROBOTS = 4;
	Hamster** robots = new Hamster*[NUM_ROBOTS];
	Executable* executable = new HandExecutable();

	for(int i = 0; i < NUM_ROBOTS; ++i)
	{
		robots[i] = new Hamster();
		robots[i]->setExecutable(executable);
	}

	// 10 seconds
	Hamster::wait(10000);

	for(int i = 0; i < NUM_ROBOTS; ++i)
		delete robots[i];
	delete [] robots;
}

void example12(void) // connection state
{
	class HamsterConnectionListener : public ConnectionListener
	{
	public:
		void onConnectionStateChanged(const Robot* robot, int state)
		{
			switch(state)
			{
			case Connection::STATE_CONNECTED:
				printf("Example Hamster[%d] Connected: %s %s\n", robot->getIndex(), robot->getPortName(), robot->getAddress());
				break;
			case Connection::STATE_CONNECTION_LOST:
				printf("Example Hamster[%d] Connection lost\n", robot->getIndex());
				break;
			case Connection::STATE_DISCONNECTED:
				printf("Example Hamster[%d] Disconnected\n", robot->getIndex());
				break;
			case Connection::STATE_DISPOSED:
				printf("Example Hamster[%d] Disposed\n", robot->getIndex());
				break;
			}
		}

		void onConnectionError(const Robot* robot, int errorCode)
		{
			switch(errorCode)
			{
			case Connection::ERROR_NO_AVAILABLE_USB:
				printf("Example Hamster[%d] No available USB to BLE bridge\n", robot->getIndex());
				break;
			case Connection::ERROR_ROBOT_NOT_CONNECTED:
				printf("Example Hamster[%d] Not connected\n", robot->getIndex());
				break;
			}
		}
	};

	ConnectionListener* listener = new HamsterConnectionListener();
	Hamster* robot = new Hamster(listener);

	// 10 seconds
	Hamster::wait(10000);

	delete robot;
	delete listener;
}

void example13(void) // data monitoring
{
	class HamsterDataChangedListener : public DeviceDataChangedListener
	{
	public:
		void onDeviceDataChanged(const Device* device, const void* values)
		{
			switch(device->getId())
			{
			case Hamster::LEFT_PROXIMITY:
				printf("Left Proximity: %d\n", ((int*)values)[0]);
				break;
			case Hamster::RIGHT_PROXIMITY:
				printf("Right Proximity: %d\n", ((int*)values)[0]);
				break;
			case Hamster::LEFT_FLOOR:
				printf("Left Floor: %d\n", ((int*)values)[0]);
				break;
			case Hamster::RIGHT_FLOOR:
				printf("Right Floor: %d\n", ((int*)values)[0]);
				break;
			}
		}
	};

	DeviceDataChangedListener* listener = new HamsterDataChangedListener();
	Hamster* robot = new Hamster();
	robot->addDeviceDataChangedListener(listener);

	// 10 seconds
	Hamster::wait(10000);

	delete robot;
	delete listener;
}

void example14(void) // inheritance
{
	class MyHamster : public Hamster
	{
	public:
		void onExecute(Robot* robot)
		{
			int leftProximity = robot->read(Hamster::LEFT_PROXIMITY);
			if(leftProximity > 40)
			{
				robot->write(Hamster::LEFT_WHEEL, -30);
				robot->write(Hamster::RIGHT_WHEEL, -30);
			}
			else
			{
				robot->write(Hamster::LEFT_WHEEL, 30);
				robot->write(Hamster::RIGHT_WHEEL, 30);
			}
		}

		void onDeviceDataChanged(const Device* device, const void* values)
		{
			if(device->getId() == Hamster::LEFT_PROXIMITY)
				printf("Left Proximity: %d\n", ((int*)values)[0]);
		}
	};

	Hamster* robot = new MyHamster();

	// 10 seconds
	Hamster::wait(10000);

	delete robot;
}

int _tmain(int argc, _TCHAR* argv[])
{
	example01(); // simple movement
	//example02(); // acceleration
	//example03(); // led
	//example04(); // basic movement
	//example05(); // staggering walk
	//example06(); // siren
	//example07(); // theremin sound
	//example08(); // simple hand follower
	//example09(); // dual theremin sound
	//example10(); // mutiple basic movement
	//example11(); // multiple hand follower
	//example12(); // connection state
	//example13(); // data monitoring
	//example14(); // inheritance

	return 0;
}
