#!/usr/bin/perl -w
use strict;

require Getopt::Std;
my %opts;

my ($user,$nice,$sys,$idle,$apmstate,$charge,$chargenumeral,$acsave,$VERBOSE,$batterypower,$deltaidle,$fullpower);
my $baselineidle = 0;

# Set initial power expenditure modes
system("tpctl --quiet -pma=high > /dev/null");
system("tpctl --quiet -pmb=high > /dev/null");
$fullpower = 1;

# Install Signal Handlers
$SIG{QUIT} = $SIG{PIPE} = $SIG{INT} = $SIG{USR1} = $SIG{USR2} = \&signalhandler;

Getopt::Std::getopt(':v',\%opts);
if (exists($opts{v})) {
	$VERBOSE=1;
}
else {
	$VERBOSE=0;
}

while (1) {
	# Get CPU status information
	open(STAT,"/proc/stat") or die $!;
	$_ = <STAT>;
	close(STAT);

	# Parse the CPU status information
	($user,$nice,$sys,$idle) = /^cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/;

	# Get power status information
	open(APM,"/proc/apm") or die $!;
	$_ = <APM>;
	close(APM);

	# Parse the power status information
	($apmstate,$charge) = /^\S+\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)/;

	if ($apmstate eq '0x00') { # We're on battery power
		if (!$batterypower) { # But we weren't before
			print "apmiser: Now on battery---will start saving power.\n" if $VERBOSE;
			$batterypower = 1;
		}
	}
	else { # We're on AC power
		if ($batterypower) { # But we were on battery power before
			print "apmiser: Now on AC power.\n" if $VERBOSE;
			$batterypower = 0;
		}

		# Find out charge level
		$chargenumeral = $charge;
		$chargenumeral =~ s/%//g;

		if ($chargenumeral < 95) { # We're under 95% charge
			if (!$acsave) { # But we weren't previously saving power
				print "apmiser: Will start saving AC power for charging ($charge).\n" if $VERBOSE;
				$acsave = 1;
			}
	    	}
	    	else { # We're at 95% charge or higher
			if ($acsave) { # And we were previously saving power
			    	print "apmiser: Will stop saving AC power for charging ($charge).\n" if $VERBOSE;
			    	system("tpctl --quiet -pma=high > /dev/null"); # U-G-L-Y
				$acsave = 0;
			}	
		}
	}

	# Calculate number of jiffies (well, not quite) we've been idling since last iteration.
	$deltaidle = $idle - $baselineidle; 

	if ($baselineidle && ($batterypower || $acsave)) { 
		# This isn't the first iteration and we are saving power.
		if ($deltaidle < 5) { # We're using the CPU intensely
			if (!$fullpower) { # But we're not at full power
				print "apmiser: Full power, Mr. Scott! ($deltaidle idle jiffies/200ms)\n" if $VERBOSE;
				system("tpctl --quiet -pmb=high > /dev/null") if ($batterypower); # U-G-L-Y
				system("tpctl --quiet -pma=high > /dev/null") if ($acsave); # U-G-L-Y
				$fullpower = 1;
			}
		}
		else { # We're not using the CPU intensely
			if ($fullpower) { # But we're at full power
				print "apmiser: Stand down, Mr. Scott. ($deltaidle idle jiffies/200ms)\n" if $VERBOSE;
				system("tpctl --quiet -pmb=auto > /dev/null") if ($batterypower); # U-G-L-Y
				system("tpctl --quiet -pma=auto > /dev/null") if ($acsave); # U-G-L-Y
				$fullpower = 0;
			}
		}
	}

	$baselineidle = $idle;

	# Sleep for 200ms
	select(undef, undef, undef, 0.2); 
}

sub signalhandler {
	# It seems a signal was sent
	# Restore power expenditure modes to defaults
	print "apmiser: Signal caught---restoring default power expenditure modes and exiting.\n" if $VERBOSE;
	system("tpctl --quiet -pma=high > /dev/null");
	system("tpctl --quiet -pmb=auto > /dev/null");
	exit(1);
}

