#include <stdint.h>
#include <iostream>
#include "socket.h"
#include "user_interface_thread.h"
#include "motor_interogator.h"

using namespace std;

void* UserInterfaceThread::Run(void* parameter)
{
	try {
		tcp_listener telnet(m_TelnetPortNumber);
		telnet.listen();
		for(;;) {
			processCommands(telnet.accept()); // Wait for someone to connect
		}
	}
	catch (socket_error_ex& e) {

		cout << "Exception: " << e.what() << endl;
		cout << "Err=" << e.whaterr() << endl;
		cout << "Txt=" << e.whatsystext() << endl;
	}
	catch (socket_error& e) {
		cout << "Exception: " << e.what() << endl;
	}
	return NULL;
}

void UserInterfaceThread::processCommands(tcp_socket telnetSocket)
{
	uint32_t	bytesReceived;

	try {
		string 				request;
		string 				response;
		string 				command;
		string::size_type	position;

		telnetSocket.set_input_formatter(new line_input_formatter());
		for (;;) {
			telnetSocket.send("\nEsp Profiler ==> ");
			bytesReceived = telnetSocket.recv(request);
			position = 0;
			command = nextToken(request," \t\r\n", position);
			if (command == "wm") {
				position = position + 1;
				command = nextToken(request, "\r\n", position);
				m_Winch.Command(command, response);
				response += "\n";
				if (response.length() >= 0)
					telnetSocket.send(response);
			} else if (command == "lw") {
				position = position + 1;
				command = nextToken(request, "\r\n", position);
				m_LevelWind.Command(command, response);
				response += "\n";
				telnetSocket.send(response);
			} else if (command == "wmrpm") {
				position = position + 1;
				command = nextToken(request, "\r\n", position);
				stringstream ss(command);
				double enteredRPM;
				ss >> enteredRPM;
				if (ss.fail()) {
					string s = "Unable to format ";
					s += command;
					s += " as a number!";
					telnetSocket.send(s);
				} else {
					string s = "Setting RPM = " + command;
					m_Controller.SetWinchRPM(enteredRPM);
					telnetSocket.send(s);
				}
			} else if (command == "lp") {
				position = position + 1;
				command = nextToken(request, "\r\n", position);
				stringstream ss(command);
				double enteredLoggingPeriod;
				ss >> enteredLoggingPeriod;
				if (ss.fail()) {
					string s = "Unable to format ";
					s += command;
					s += " as a number!";
					telnetSocket.send(s);
				} else {
					string s = "Setting Logging Period = " + command;
					m_Logger.LoggingPeriod(enteredLoggingPeriod);
					telnetSocket.send(s);
				}
			} else if (command == "depth") {
				position = position + 1;
				command = nextToken(request, "\r\n", position);
				stringstream ss(command);
				double enteredDepth;
				ss >> enteredDepth;
				if (ss.fail()) {
					string s = "Unable to format ";
					s += command;
					s += " as a number!";
					telnetSocket.send(s);
				} else {
					string s = "Setting depth = " + command;
					m_Controller.DesiredDepth(enteredDepth);
					telnetSocket.send(s);
				}
			} else if (command == "start") {
				m_Controller.StartController();
				m_LevelWind.Start();
				m_Winch.Start();
				telnetSocket.send("Starting Profiler");
			} else if (command == "stop") {
				m_Controller.StopController();
				m_Winch.Stop();
				m_LevelWind.Stop();
				telnetSocket.send("All Stop");
			} else if (command == "?") {
				telnetSocket.send("wm <command> Send <command> to the winch motor controller\n");
				telnetSocket.send("lw <command> Send <command> to the level wind motor controller\n");
				telnetSocket.send("start        Start winch and level wind motors\n");
				telnetSocket.send("stop         Stop winch and level wind motors\n");
				telnetSocket.send("wprpm <rpm>  Set winch <rpm>\n");
				telnetSocket.send("lp <period>  Set logging update period");
			} else {
				telnetSocket.send("Unknown command, type ? for a list of commands");
			}
		}
	}
	catch (socket_error_ex& e) {
		m_Winch.Stop();
		m_LevelWind.Stop();
		cout << "User Interface lost communication" << endl;
		cout << "Exception: " << e.what() << endl;
		cout << "Err=" << e.whaterr() << endl;
		cout << "Txt=" << e.whatsystext() << endl;
	}
	catch (socket_error& e) {
		cout << "Exception: " << e.what() << endl;
	}
}

string UserInterfaceThread::nextToken(const string& line,
		const string& delim,
		string::size_type& first)
{
	string::size_type last = line.find_first_of(delim, first);
	string next(line.substr(first, last));
	first = last;
	return next;
}


