#!/usr/bin/perl

use strict;
use warnings;
use IO::File;
use Getopt::Long qw(:config no_ignore_case bundling);

$| = 1;

sub help_message {
    my $help = 
"machpause-admin must be run under root account.

Syntax:
  -l xxx       list configuration [xxx = username or 1-7 (day of week)] 
  -L           list all configuration
  -s           set new configuration (use with -u, -t, and -d or -a)
  -u xxx       username xxx
  -t time      time is user's business hours (in minutes)
  -d day       day of week (1, 2, 3, 4, 5, 6 or 7)
  -r           remove old configuration (use with -u, -d, or -a)
  -a           all options (looking examples)
  -R           WARNING: this option remove config- and cache directories!!!

Example set configuration:
  machpause-admin -s -u fritz -t 120 -d 5   (120 minutes for fritz on friday)
  machpause-admin -s -u fritz -t 120 -a     (120 minutes for fritz all days)
  
Example remove configuration:
  machpause-admin -r -u fritz -d 5          (remove fritz on friday)
  machpause-admin -r -u fritz -a            (remove fritz all days)

";
    print $help;
    exit 0;
}

use vars qw($opt_a $opt_d $opt_h $opt_L $opt_l $opt_r $opt_R $opt_s $opt_t $opt_u);

GetOptions("a", "d=i", "h", "L", "l=s", "r", "R", "s", "t=i", "u=s") 
    || usage('no args');

if ($opt_h){
    help_message();
}

my $uid = $<; $< = $>;

if ($uid != 0) {
    print "$0 must be run under root account!\n";
    exit 1;
}

# list options
if ($opt_L){
    _list_config_all();
}
if ($opt_l){
    _list_config($opt_l);
}

# set options
if ($opt_s){
    my $username = _check_username($opt_u);
    my $usertime = _check_usertime($opt_t);
    if ($opt_a){
	 _write_config_all($username, $usertime);
	 exit 0;
    }
    my $userday = _check_weekday($opt_d);
    _write_config($username, $usertime, $userday);
    exit 0;
}

# remove options
if ($opt_r){
    my $username = _check_username($opt_u);
    if ($opt_a){
	_delete_config_all($username);
	exit 0;
    }
    my $userday = _check_weekday($opt_d);
    _delete_config($username, $userday);
    exit 0;
}
if ($opt_R){
    _delete_config_directories();
    exit 0;
}

usage('no args');

sub usage {
    my $mes = shift;
    print "usage $mes\n";
    exit 1;
}

sub _list_config {
    my $list = shift;
    if (!$list) {
        usage("Error: list arg is not defined!\n");
    }    
    if ( ($list =~ / \A [1-7] \z /xms) ) {
	_list_config_day($list);
	exit 0;
    }
    if ( ($list =~ / \A [a-z, A-Z, 0-9]+ \z /xms) ) {
	_list_config_user($list);
	exit 0;
    }
    usage("Error: username is not an alphanumeric string!\n");
}

sub _get_day_list {
    return qw {Monday Tuesday Wednesday Thursday Friday Saturday Sunday};
}

sub _get_day_string {
    my $day = shift;
    my @weekdays = _get_day_list();
    $day -= 1;
    return $weekdays[$day];
}

sub _list_config_day {
    my $daynum = shift;
    my $day = _get_day_string($daynum);
    print "userlist: $day\n";
    _list_user_data($day);
    return;
}

sub _list_config_user {
    my $username = shift;
    my @weekdays = _get_day_list();
    my $config_dir = '/etc/machpause';
    foreach my $day (@weekdays) {
	print "$day: ";
	my $anz = 0;
	if (-d "$config_dir/$day") {
	    opendir(DIR, "$config_dir/$day") || die "Error: cannot listing $config_dir/$day: $!\n";
	    foreach my $data (readdir(DIR)) {
		next if $data eq "." || $data eq "..";
		if (! ($data =~ / \A $username \z /xms) ) {
		    next;
		}
		$anz = 1;
        	print "$data ";
        	print _get_user_data("$config_dir/$day/$data");
        	print "\n";
	    }
	    closedir(DIR);
	    if (!$anz) {
		print "no config for user \'$username\' found.\n";
	    }
	}
	else {
	    print "config directory not found.\n";
	}
    }
    exit 0;
}

sub _list_config_all {
    for (1..7) {
	_list_config_day($_);
    }
    exit 0;
}

sub _list_user_data {
    my $day_dir = shift;
    my $config_dir = '/etc/machpause';
    if (-d "$config_dir/$day_dir") {
	my $anz = 0;
	opendir(DIR, "$config_dir/$day_dir") || die "Error: cannot listing $config_dir/$day_dir: $!\n";
	foreach my $data (sort (readdir(DIR))) {
    	    next if $data eq "." || $data eq "..";
	    $anz = 1;
    	    print "$data ";
	    print _get_user_data("$config_dir/$day_dir/$data");
	    print "\n";
	}
	closedir(DIR);
	if (!$anz) {
	    print "no config found.\n";
	}
    }
    else {
	print "config directory not found.\n";
    }
    return;
}

sub _get_user_data {
    my $file = shift;
    my $time = 0;
    if (-f "$file") {
        my $cfile = IO::File->new("<$file");
        if ($cfile) {
            NUMBER:
            while (<$cfile>) {
		if ( / \A \d+ \z /xms ) {
                    $time = $_;
		    chomp($time);
                    last NUMBER;
        	}
            }
            $cfile->close();
        }
    }
    return $time;
}

sub _write_config_all {
    my $user = shift;
    my $time = shift;
    for (1..7) {
	_write_config($user, $time, $_);
    }
    return;
}

sub _write_config {
    my $user = shift;
    my $time = shift;
    my $daynum  = shift;    
    my $conf_dir  = '/etc/machpause';
    my $cache_dir = '/var/cache/machpause';
    my $day = _get_day_string($daynum);
    _delete_config_file("$conf_dir/$day/$user");
    _delete_config_file("$cache_dir/$day/$user");
    _create_config_directory($day);
    my $file = IO::File->new(">$conf_dir/$day/$user");
    if ($file) {
        chmod(0644, $file);
	print "Info: create $conf_dir/$day/$user\n";
        print {$file} $time;
        $file->close();
    }
    else {
	usage ("Error: cannot create $conf_dir/$day/$user");
    }
    return;
}

sub _delete_config_all {
    my $user = shift;
    for (1..7) {
	_delete_config($user, $_);
    }
    return;
}

sub _delete_config {
    my $user = shift;
    my $daynum  = shift;
    my $conf_dir  = '/etc/machpause';
    my $cache_dir = '/var/cache/machpause';
    my $day = _get_day_string($daynum);
    _delete_config_file("$conf_dir/$day/$user");
    _delete_config_file("$cache_dir/$day/$user");
    return;
}

sub _delete_config_file {
    my $file = shift;
    if (-f "$file") {
        if (unlink("$file")) {
	    print "Info: remove $file\n";
        }
	else {
	    usage("Error: cannot remove $file: $!\n");
	}
    }
    return;    
}

sub _delete_config_directories {
    my $conf_dir  = '/etc/machpause';
    my $cache_dir = '/var/cache/machpause';
    if (-d $conf_dir) {
	system ("rm -r -f -v $conf_dir");
    }
    if (-d $cache_dir) {
	system ("rm -r -f -v $cache_dir");
    }
    return;
}

sub _create_config_directory {
    my $day_dir = shift;
    my $config_dir = '/etc/machpause';
    if (! -d $config_dir) {
	if ( mkdir($config_dir) ) {
    	    chmod (0755, $config_dir);
        }
	else {
	    print "Error: cannot create $config_dir: $!";
	    exit 1;
	}
    }
    if (! -d "$config_dir/$day_dir") {
        if ( mkdir ("$config_dir/$day_dir") ) {
            chmod (0755, "$config_dir/$day_dir");
        }
        else {
            print "Error: cannot create $config_dir/$day_dir: $!";
            exit 1;
        }
    }
    return;    
}

sub _check_username {
    my $testuser = shift;
    if (!$testuser) {
        usage("Error: username is not defined!\n");
    }
    if (! ($testuser =~ / \A [a-z, A-Z, 0-9]+ \z /xms) ) {
        usage("Error: username is not an alphanumeric string!\n");
    }
    return $testuser
}

sub _check_usertime {
    my $utime = shift;
    if (!$utime) {
        usage("Error: time for user is not defined!\n");
    }
    if (! ($utime =~ / \A [0-9]+ \z /xms) ) {
        usage("Error: time is not an number!\n");
    }
    if ($utime < 10) {
        usage("Error: usertime should NOT be littler than 10 minutes!\n");
    }
    if ($utime > 1440) {
        usage("Error: usertime should NOT be greater than 1440 minutes!\n");
    }    
    return $utime
}

sub _check_weekday {
    my $weekday = shift;
    if (!$weekday) {
        usage("Error: weekday is not defined!\n");
    }
    if (! ($weekday =~ / \A [1-7] \z /xms) ) {
        usage("Error: weekday is not an correctly number!\n");
    }
    return $weekday
}

### eof
