/*
 * Kangaroo Punch MultiPlayer Game Server Mark II
 * Copyright (C) 2020-2021  Scott Duensing
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */


#include "settings.h"
#include "welcome.h"

#include "taglist.h"
#include "task.h"
#include "comport.h"
#include "timer.h"
#include "config.h"

#include "window.h"
#include "button.h"
#include "frame.h"
#include "radio.h"
#include "textbox.h"
#include "updown.h"
#include "label.h"


#define GROUP_COM  1

#define PORT_NONE        0
#define PORT_NO_MODEM    1
#define PORT_BAD_MODEM   2
#define PORT_GOOD_MODEM  3

#define TITLE_LEN  80


typedef struct PortS {
	uint8_t  status;
	char     title[TITLE_LEN];
	uint8_t  selected;
	uint8_t  enabled;
	RadioT  *rdoCOM;
} PortT;


static WindowT        *_winDetecting;
static LabelT         *_lblOneMoment;
static WindowT        *_winSettings;
static FrameT         *_frmComPorts;
static FrameT         *_frmServer;
static ButtonT        *_btnOkay;
static TextboxT       *_txtServer;
static UpdownT        *_updPort;
static PortT           _port[4];
static widgetCallback  _done;


static void btnOkayClick(WidgetT *widget);


static void btnOkayClick(WidgetT *widget) {
	uint8_t  x;
	RadioT  *selected = radioSelectedGet(_port[0].rdoCOM);

	(void)widget;

	// Save selected COM port.
	for (x=0; x<4; x++) {
		if (selected == _port[x].rdoCOM) {
			__configData.serialCom = x + 1;
			break;
		}
	}

	// Save server info.
	free(__configData.serverHost);
	__configData.serverHost = strdup(textboxValueGet(_txtServer));
	__configData.serverPort = updownValueGet(_updPort);

	// Return to calling routine.
	guiDelete(D(_winSettings));
	_done(NULL);
}


void taskSettings(void *data) {

	int32_t  rc;
	uint32_t len;
	char     buffer[1024];
	uint8_t  selected = 1;

	_done = (widgetCallback)data;

	TagItemT uiDetecting[] = {
		T_START,
			T_WINDOW, O(_winDetecting),
				T_TITLE, P("Detecting Modems"),
				T_WIDTH, 200, T_HEIGHT, 100,
				T_LABEL, O(_lblOneMoment),
					T_X, 25, T_Y, 25,
					T_TITLE, P("One Moment Please!"),
				T_LABEL, T_DONE,
			T_WINDOW, T_DONE,
		T_END
	};

	tagListRun(uiDetecting);
	taskYield();   // Cause dialog to paint.

	// Scan the COM ports for a compatable modem.
	for (int x=0; x<4; x++) {
		rc = comOpen(x, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
		if (rc == SER_SUCCESS) {
			snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
			comWrite(x, buffer, strlen(buffer));
			timerQuarterSecondsWait(4);
			len = comRead(x, buffer, 1023);
			buffer[len] = 0;
			if (strstr(buffer, "OK")) {
				snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - SoftModem Found!", x + 1);
				_port[x].status   = PORT_GOOD_MODEM;
				_port[x].selected = selected;
				_port[x].enabled  = 1;
				selected = 0;
			} else {
				if (strstr(buffer, "ERROR")) {
					snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - Incompatable Modem", x + 1);
					_port[x].status   = PORT_BAD_MODEM;
					_port[x].selected = 0;
					_port[x].enabled  = 0;
				} else {
					snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - No Modem", x + 1);
					_port[x].status   = PORT_NO_MODEM;
					_port[x].selected = 0;
					_port[x].enabled  = 0;
				}
			}
			comClose(x);
		} else {
			snprintf(_port[x].title, TITLE_LEN - 1, "COM%d - Not Present", x + 1);
			_port[x].status   = PORT_NONE;
			_port[x].selected = 0;
			_port[x].enabled  = 0;
		}
	}

	guiDelete(D(_winDetecting));

	TagItemT uiSettings[] = {
		T_START,
			T_WINDOW, O(_winSettings),
				T_TITLE, P("Settings"),
				T_WIDTH, 300, T_HEIGHT, 295,

				T_FRAME, O(_frmComPorts),
					T_X, 10, T_Y, 5, T_WIDTH, 266, T_HEIGHT, 100,
					T_TITLE, P("COM Ports"),
				T_FRAME, T_DONE,

				T_FRAME, O(_frmServer),
					T_X, 10, T_Y, 110, T_WIDTH, 266, T_HEIGHT, 100,
					T_TITLE, P("Server"),
					T_TEXTBOX, O(_txtServer),
						T_X, 5, T_WIDTH, 250,
						T_TITLE, P("Address:"),
						T_VALUE, P(__configData.serverHost),
					T_TEXTBOX, T_DONE,
					T_UPDOWN, O(_updPort),
						T_X, 5, T_Y, 30, T_WIDTH, 250,
						T_TITLE, P("   Port:"),
						T_VALUE, __configData.serverPort,
						T_MINIMUM, 1,
						T_MAXIMUM, 65535,
					T_UPDOWN, T_DONE,
				T_FRAME, T_DONE,

				T_BUTTON, O(_btnOkay),
					T_X, 225, T_Y, 225,
					T_TITLE, P("Okay"),
					T_CLICK, P(btnOkayClick),
				T_BUTTON, T_DONE,

			T_WINDOW, T_DONE,
		T_END
	};

	tagListRun(uiSettings);

	// If we found more than one, use the last selected.
	if (__configData.serialCom > 0 && __configData.serialCom < 4) {
		if (_port[__configData.serialCom - 1].enabled) {
			for (len=0; len<4; len++) {
				_port[len].selected = 0;
			}
			_port[__configData.serialCom - 1].selected = 1;
		}
	}

	// Add COM discovery to GUI.
	rc = 0;
	for (len=0; len<4; len++) {
		_port[len].rdoCOM = radioNew(5, rc, _port[len].title, GROUP_COM);
		if (_port[len].selected) radioSelectedSet(_port[len].rdoCOM);
		widgetEnableSet(W(_port[len].rdoCOM), _port[len].enabled);
		guiAttach(W(_frmComPorts), W(_port[len].rdoCOM));
		rc += 20;
	}
}
