/*
  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 <http://www.gnu.org/licenses/>. 
*/

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <windows.h>

#include "parser.h"
#include "serial.h"
#include "commands.h"
#include "spi.h"

typedef struct {
	const char *cmd;
	int (*pf)(int argc, char *argv[]);
	const char *help;
} centry;

bool inavail() {
	long int nchars;
	if(fseek(stdin, 0, SEEK_END) != 0) return false;
	if((nchars = ftell(stdin)) < 0)    return false;
	if(fseek(stdin, 0, SEEK_SET) != 0) return false;
	return nchars > 0;
}

centry clist[] = {
	{ "enum",   enumerate, "Enumerate all connected devices" },
	{ "target", target,    "Target device" },
	{ "setid",  setid,     "Program new ID" },
	{ "config", config,    "Configuration manipulation" },
	{ "get",    get,       "Perform readout" },
	{ "set",    set,       "Set output" },
};

int main(int argc, char *argv[]) {
	if(argc != 2) {
		printf("Please specify device on command line, typically:\n");
		printf("\tWindows: %s COM*:\n", argv[0]);
		printf("\tLinux:   %s /dev/ttyACM*:\n", argv[0]);
		printf("\tMac:     %s /dev/tty.usbmodem*\n", argv[0]);
		return 1;
	}
	
	printf("Opening connection... ");
	if(!sopen(argv[1])) {
		printf("\nUnable to open device \"%s\"\n", argv[1]);
		return 2;
	}

	if(!sconfig("9600,N,8,1")) {
		printf("\nUnable to configure device \"%s\" for 9600:8N1\n", argv[1]);
		return 3;
	}

	printf("OK!\nInitializing... ");
	if(!spi_init()) {
		printf("\nUnable to initialize communication.\nMake sure you have the configurator sketch loaded.");
		return 4;
	}
	printf("OK!\n\n");

	char command[80];
	unsigned int n;
	while(1) {
		printf("> ");
		fgets(command, 80, stdin);
		argv = parse(command, &argc);
		if(argc) {
			if(!strcmp(argv[0], "exit")) break;
			else if(!strcmp(argv[0], "help")) {
				printf("Available commands:\n");
				for(n = 0; n < sizeof(clist) / sizeof(clist[0]); n++) {
					printf("%s\t%s\n", clist[n].cmd, clist[n].help);
				}
			} else {
				for(n = 0; n < sizeof(clist) / sizeof(clist[0]); n++) {
					if(!strcmp(argv[0], clist[n].cmd)) {
						clist[n].pf(argc, argv);
						break;
					}
				}
				if(n == sizeof(clist) / sizeof(clist[0])) printf("Unknown command %s - try help\n", argv[0]);
			}
		}
		if(argv) free(argv);
	}

	printf("\nClosing connection... ");
	sclose();
	printf("OK\n");

	return 0;
}