package emeter_lib;

# emeter_lib is a library for reading information 
# out of the e-meter



use IO::Socket;
use IO::Select;
use Fcntl;

sub new {
	my $type = shift;
	my $self = {};
	bless($self, $type);
}

sub fork {
	# this function forks off the communications thread
	# it takes one argument, a comm handler to the dash
	# it creates a unix domain socket in /tmp
	# to handle receiving input

	my $self = shift;
	my $ob = shift;

	my $mainsock;
	my $select;
	my $sock;
	my %map;
	my $cmd;
	my %update;

	$map{"time"} = 0;
	$map{"kwhrs"} = 1;
	$map{"amps"} = 2;
	$map{"volts"} = 3;
	$map{"ahrs"} = 4;
	$map{"peukert_amps"} = 5;
	$map{"time_remaining"} = 6;
	$map{"bar_graph_state"} = 7;
	$map{"temp"} = 8;
	$map{"raw"} = 9;
	$map{"len"} = 10;
	
	my @chan = (0,0,0,0,0,0);


	if(fork()) {
		return;
	} else {

		# we are the child thread
		# we basically run in circles, screaming
		# and shouting
		# we write the dash, and poll the
		# tcp socket for updates

		$SIG{CHLD} = IGNORE;
		$SIG{INT} = IGNORE;
	
		$mainsock = IO::Socket::INET->new(Listen => 5, 
						  LocalPort => 6557,
						  Proto => 'tcp',
						  ReuseAddr=> 1,
						  );
	
		die "Failed to open port 6557 (already running?)" if(!$mainsock);

		$select = new IO::Select();
		
		close(STDIN);
		close(STDOUT);
		close(STDERR);
	
		$select->add($mainsock);

		$alive = 1;

		while($alive) {
			@readable = $select->can_read(0.20);
			foreach $sock (@readable) {
				if($sock eq $mainsock) {
					# new connection
					$sock = $mainsock->accept();
					$sock->timeout(0);
					fcntl($sock, F_SETFL, O_NONBLOCK);

					print $sock "EMETER>";
					$select->add($sock);
				} else {

		$sock->recv($in,255,0);

		if(! defined $in) {
			$select->remove($sock);
			$sock->close();
			delete $update{$sock}{val};
			delete $update{$sock}{handle};
			delete $update{$sock};
		} else {
			($cmd, $val) = $in =~ /^\W*(\w*)\W*(\w*)\W*$/;

			$alive = 0 if(($cmd eq "shutdown") && ($val eq "now" ));

			if($cmd eq "update") {
				if($val eq "1") {
					$update{"$sock"} = 1;
					$update{"$sock"}{val} = 1;
					$update{"$sock"}{handle} = $sock;
				} else {
					$update{"$sock"} = 1;
					$update{"$sock"}{val} = 0;
					$update{"$sock"}{handle} = $sock;
				}
			}
	
			if($cmd eq "quit") {
				if($val eq "now") {
					$sock->close();
					delete $update{$sock}{val};
					delete $update{$sock}{handle};
					delete $update{$sock};
				}
			}
	
			if($cmd eq "read") {
				if(! defined $map{"$val"}) {
					print $sock "ERR no such val $val\n";
				} else {
					$cmd = $chan[$map{"$val"}];

					print $sock "$cmd\n";
				}
			}

		}
		print $sock "EMETER>";
		}
		}

		($len, $data) = $ob->read(60);
		chop($data);
		print "loop\n";

		$chan[9] = $data;
		$chan[10] = $len;

		if($len == 60) {
			@chan = split(/,/,$data);
		}
		$c = 0;
		
		

		print "see\n";
		@writable = $select->can_write(0.05);
		print "do\n";

		foreach $key (@writable) {
			
			if((defined $update{$key}) && $update{$key}{val} == 1) {
				$sock = $update{$key}{handle};
				print "$sock\n";
				$sock->write("UPDATE\n");
			}
		}
		print "bah\n";

		}
	}
		die;
}

1;
