use Irssi;
use strict;
use FileHandle;

use vars qw($VERSION %IRSSI);

$VERSION = "0.9.1.2";
%IRSSI = (
	authors     => 'Andreas \'ads\' Scherbaum <ads@ufp.de>',
	name        => 'screen_away',
	description => 'set (un)away, if screen is attached/detached',
	license     => 'GPL v2',
	url         => 'none',
);

# screen_away irssi module
#
# written by Andreas 'ads' Scherbaum <ads@ufp.de>
#
# changes:
#  01.10.2004 added setting screen_away_delay          (by S. Groeneveld)
#             added setting screen_away_show_status    (by S. Groeneveld)
#
#           Notes:
#           - screen_away_delay (int value) will prevent setting status to away until the
#             specified amount of cycles (of screen_away_repeat seconds) have passed.
#           - set screen_away_show_status to OFF to suppress any status messages#
# 
#  07.02.2004 fix error with away mode
#             thanks to Michael Schiansky for reporting and fixing this one
#
#
# usage:
#
# put this script into your autorun directory and/or load it with
#  /SCRIPT LOAD <name>
#
# there are 4 settings available:
#
# /set screen_away_active ON/OFF/TOGGLE
# /set screen_away_repeat <integer>
# /set screen_away_message <string>
# /set screen_away_window <string>
#
# active means, that you will be only set away/unaway, if this
#   flag is set, default is ON
# repeat is the number of seconds, after the script will check the
#   screen status again, default is 5 seconds
# message is the away message sent to the server, default: not here ...
# window is a window number or name, if set, the script will switch
#   to this window, if it sets you away, default is '1'
#
# normal you should be able to rename the script to something other
# than 'screen_away' (as example, if you dont like the name) by simple
# changing the 'name' parameter in the %IRSSI hash at the top of this script


# variables
my $timer_name = undef;
my $away_status = 0;

# Register formats
Irssi::theme_register(
[
	'screen_away_crap', 
	'{line_start}{hilight ' . $IRSSI{'name'} . ':} $0'
]);

# if we are running
my $screen_away_used = 0;

# try to find out, if we are running in a screen
# normal this would be:  irssi -(parent)-> shell -(parent)-> screen
# first get the parent pid of our parent
my $fh = new FileHandle;
if (!open($fh, "/proc/" . getppid() . "/status")) {
	# just return, we will never be called again
	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
		"could not open status file for parent process (pid: " . getppid() . "): $!");
	return;
}
my @file = <$fh>;
close($fh);

# get parent pid
my $screen_pid = -1;
foreach (@file) {
	if ($_ =~ /^PPid:[\s\t]+(\d+).*/s) {
		$screen_pid = $1;
	}
}
if ($screen_pid == -1) {
	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
		"could not find parent pid from pid " . getppid());
	return;
}

# now open this parent and look for the name
$fh = new FileHandle;
if (!open($fh, "/proc/$screen_pid/status")) {
	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
		"could not open status file for parent process (pid: $screen_pid): $!");
	return;
}
my @file = <$fh>;
close($fh);

# now check, if the name is 'screen'
if ($file[0] !~ /^Name:[\s\t]+screen/si) {
	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
		"not running inside a screen");
	return;
}

my ($socket_name, $socket_path);

# search for socket
# normal we could search the socket file, ... if we know the path
# but so we have to call one time the screen executable
my $socket = `screen -ls`;
my $running_in_screen = 0;
# locale doesnt seems to be an problem (yet)
if ($socket !~ /^No Sockets found/s) {
	# ok, should have only one socket
	$socket_name = $socket;
	$socket_name =~ s/^[^\n]+\n[\s\t]($screen_pid\.[^\s\t]+).+$/$1/s;
	$socket_path = $socket;
	$socket_path =~ s/^.+\d+ Sockets? in ([^\n]+)\.\n.+$/$1/s;
	if (length($socket_path) != length($socket) and length($socket_path) != length($socket)) {
		# only activate, if both strings are changed
		$screen_away_used = 1;
	} else {
		Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
			"error reading screen informations from:");
		Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
			"$socket");
		return;
	}
}

# last check
if ($screen_away_used == 0) {
	return;
}

# build complete socket name
$socket = $socket_path . "/" . $socket_name;

# register config variables
Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_active', 1);
Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_show_status', 1);
Irssi::settings_add_int('misc', $IRSSI{'name'} . '_repeat', 5);
Irssi::settings_add_int('misc', $IRSSI{'name'} . '_delay', 4);
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_message', "not here ...");
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_window', "1");

# init process
screen_away();

# prints a status message if allowed
sub status_msg {
	my ($msg) = @_;		
	return unless (Irssi::settings_get_bool($IRSSI{'name'} . '_show_status') == 1);
	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap', $msg);
}

# screen_away()
#
# check, set or reset the away status
#
# parameter:
#   none
# return:
#   0 (OK)
#
# Dracula's hack:
#   $away_status = 0    Script has just been activated
#   $away_status = 1    Status set to away
#   $away_status = 2    Status set to back
#
#   $away_status < -1   Tracking amount of cycles until delaytime has expired
#	$away_status = -1   Delay has expired
#   
sub screen_away {
	my ($detached,@screen, $screen);

	# Only run, if activated
	if (Irssi::settings_get_bool($IRSSI{'name'} . '_active') == 1) {
		if ($away_status == 0) {
			# display init message at first time
			Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',	
				"Activating $IRSSI{'name'} (interval: " . Irssi::settings_get_int($IRSSI{'name'} . '_repeat') . " seconds)");
    	}
		# Get actual screen status
		my @screen = stat($socket);
		# 00100 is the mode for "user has execute permissions", see stat.h
		if (($screen[2] & 00100) == 0) {
			# no execute permissions, Detached
			$detached = 1;
		} else {
			# execute permissions, Attached
			$detached = 0;
		}

		# Check if status has changed 
		if ($detached == 1 and $away_status != 1) {
			# We're detached, check what to do

			my $delay = Irssi::settings_get_int($IRSSI{'name'} . '_delay');
	  
		  	# If no delay specified OR if delay has expired, set status to away
			if ($away_status == -1 or $delay == 0) {
			
				# If length of window is greater then 0, make this window active
				if (length(Irssi::settings_get_str($IRSSI{'name'} . '_window')) > 0) {				
					Irssi::command('window goto ' . Irssi::settings_get_str($IRSSI{'name'} . '_window'));
				}
				
				status_msg("Set status to away");
				
				my $message = Irssi::settings_get_str($IRSSI{'name'} . '_message');
				
				# We have to set a message or we wouldnt go away
				if (length($message) == 0) {
					$message = "not here ...";
				}
				
				# Go away on each server
				foreach (Irssi::servers()) {
					$_->command("AWAY -one $message") if (!$_->{usermode_away});
				}
				$away_status = 1;
				
			} elsif ($away_status < -1) {
			
				# Delay is active, and we're still detached
				$away_status += 1;
				
			} else {
			
				# Just detached, but first countdown delay
				my $repeat = Irssi::settings_get_int($IRSSI{'name'} . '_repeat');
				status_msg("About to set away status in " . ($delay * $repeat) . " seconds");
				$away_status = -$delay;
				
			}
			
		} elsif ($detached == 0 and $away_status != 2) {
	
			# We just attached, so set status to back
			status_msg("Reset away");
			foreach (Irssi::servers()) {
				$_->command('AWAY -one') if ($_->{usermode_away});
			}
			$away_status = 2;
		}
	}
	# But everytime install a new timer
	register_screen_away_timer();
	return 0;
}

# register_screen_away_timer()
#
# remove old timer and install a new one
#
# parameter:
#   none
# return:
#   none
sub register_screen_away_timer {
	if (defined($timer_name)) {
	# remove old timer, if defined
		Irssi::timeout_remove($timer_name);
	}
	# add new timer with new timeout (maybe the timeout has been changed)
	$timer_name = Irssi::timeout_add(Irssi::settings_get_int($IRSSI{'name'} . '_repeat') * 1000, 'screen_away', '');
}