#ifndef X10IO_H_
#define X10IO_H_

#include <iostream>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "x10map.H"


#define X10_ALLOFF	0
#define X10_LIGHTSON	1
#define X10_ON		2
#define X10_OFF		3
#define X10_DIM		4
#define X10_BRIGHT	5
#define X10_LIGHTSOFF	6
#define X10_HAILREQ	7
#define X10_HAILACK	8
#define X10_PSD0	9
#define X10_PSD1	10
#define X10_STATON	11
#define X10_STATOFF	12
#define X10_STATREQ	13
#define X10_LAST	13
#define X10_INVALID	-1

#define X10_SELECTUNIT	16

#define COMMANDOK(x)	((x) >= 0 && (x) <= X10_LAST)
#define UNITOK(x)	((x) >= 1 && (x) <= 16)
#define HOUSEOK(x)	((x) >= 'A' && (x) <= 'P')

struct x10cmdq {
	struct x10cmdq *next;
	int cmdsize;
	char *cmd;
	int pending;
	int tries;
	time_t lasttry;
	int command;
	int house;
	int unit;
};

typedef struct configuration_t {
	char *device;
	char *map_file;
	char *socket_file;
	char *group;
	char *user;
	char *run_format;
	int device_timeout;
	int command_timeout;
	char *device_type;
	int foreground;
} CONFIGURATION;

class X10 {
public:
	X10(CONFIGURATION *config);
	virtual ~X10();
	int Open();
	int Run(CONFIGURATION *group);
	void Shutdown(void);
protected:
	int QueueBinary(int command, int house, int unit,
				int size, char *data);
	int QueueText(int command, int house, int unit, char *data);
	int ValidateCommand (int command, int hc, int uc, int count);
	void Receive (int command, int hc, int uc);
	void Retry (void);
	int Dequeue();

	virtual void ConfigDevice (struct termios *);
	virtual int CreateCommand (int command, int hc, int uc) = 0;
	virtual int ParseCommand (int size, char *cmd) = 0;
	virtual void Timeout (void);

private:
	void ProcessInput (int size, char *data);
	int Send(void);
	int ProcessPacket(int s);

	int shutdown;
	int x10_ioport;
	int server_socket;
	struct sockaddr sock;
	char *ctty;
	int rpend;
	struct x10cmdq *q;
	struct x10cmdq *tail;
	X10map *map;
	int receive_size;
	int receive_count;
	char *receive_buffer;		// Remainder buffer
	int timeout;
};

#endif

