#!/usr/bin/perl
use strict;
use warnings;

use WWW::WebKit;
use Time::HiRes qw(gettimeofday tv_interval);
use Getopt::Long;
#use IO::File;

use Glib qw(TRUE FALSE);

sub timesub {
    my $s = shift;
    if (!defined $s) {
        my $startsec = [gettimeofday()];
        return $startsec;
    } else {
        my $elapsed = tv_interval ($s, [gettimeofday]);
        $elapsed = sprintf("%.2f",$elapsed);
        return $elapsed;
    }
}

sub wk {
    my ($opt,$slurp) = @_;
    my $webkit;
    my $expect = 0;
    my $expect_ok = 0;
    my $xvfb = 1;
    if ($opt->{debug} >= 2) { $xvfb = 0 }
    #eval {
    #local $SIG{ALRM} = sub { die "alarm\n"};
    #    alarm $opt->{critical};
        $webkit = WWW::WebKit->new(xvfb => $xvfb);
        $webkit->init;
        $webkit->view->signal_connect('console-message' => sub {
                push @{ $webkit->console_messages }, $_[1];
                return TRUE;
        });
        $webkit->open($opt->{url});
        foreach my $e (@{$slurp}) {
            next if $e =~ /^#/;
            chomp $e;
            my @cm = split('\|',$e);
            if ($cm[0] eq "type") { 
                $webkit->type($cm[1],$cm[2]);
                next;
            } 
            if ($cm[0] eq "submit") {
                $webkit->submit($cm[1]);
                $webkit->wait_for_page_to_load();
                next;
            } 
            if ($cm[0] eq "click") {
                $webkit->click($cm[1]);
                $webkit->wait_for_page_to_load();
                next;
            }
            if ($cm[0] eq "check") {
                $webkit->check($cm[1]);
                next;
            }
            if ($cm[0] eq "refresh") {
                $webkit->refresh;
                next;
            }
            if ($cm[0] eq "expect") {
                my $op = $webkit->get_html_source();
                $expect++;
                if ($op =~ /$cm[1]/) {
                    $expect_ok++;
                }
                next;
            }
            if ($cm[0] eq "expect_not") {
                my $op = $webkit->get_html_source();
                $expect++;
                if ($op !~ /$cm[1]/) {
                    $expect_ok++;
                }
                next;
            }
        }
        if (defined $opt->{debug}) {
            if ($opt->{debug} >= 1) {
                my $op = $webkit->get_html_source();    
                print $op;
            }
        }
        #    alarm 0;
        #};
        #if ($@) {
        #die unless $@ eq "alarm\n";    
        #}
    my $exp = $expect - $expect_ok;
    return ($exp);
}

sub getandchk {
    my %opt;
    my @slurp;
    GetOptions(\%opt,'man','help|?','warning=s','critical=s','debug+','file=s','url=s','verbose');
    if (defined $opt{file}) {
        #my $fh = IO::File->new("< $opt{file}") or die "$!\n";
        if (-r $opt{file}) {
            #my $fh = IO::File->new("< $opt{file}");
            open(my $fh,"<",$opt{file}) or die "$!";
            flock($fh,1);
            @slurp = <$fh>;
            close($fh);
            foreach (@slurp) {
                chomp;
                my @u = split('\|',$_);
                if (!defined $opt{url}) {
                    if ($u[0] eq "url") {
                       $opt{url} = $u[1]; 
                    }
                }
            }
        } else {
            exit 2;
        }
    }
    if (!defined $opt{file} || !defined $opt{warning} || !defined $opt{critical} || !defined $opt{url}) {
        #if (!defined $opt{file}) { print "Missing config file name (-f)\n" }
        #if (!defined $opt{warning}) { print "Missing warning (-w)\n" }
        #if (!defined $opt{critical}) { print "Missing critical (-c)\n" }
        #if (!defined $opt{url}) { print "Missing url (-u)\n" }
        #    pod2usage(2);
        ender("Incorrectly defined arguments",2,\%opt,0);
    }
    if (!defined $opt{debug}) { $opt{debug} = 0 }
    return \%opt,\@slurp;
}

sub ender {
    my ($mess,$rt,$opt,$time) = @_;
    print "HTTP: $mess|time=$time" . "s;$opt->{warning};$opt->{critical};0;$opt->{critical}";
    exit $rt;
}

sub run {
    my ($opt,$slurp) = getandchk();
    my $pstart = timesub();
    my $exp = wk($opt,$slurp);
    my $pend = timesub($pstart);
    #print "$0 took $pend secs\n";
    if ($opt->{debug} == 3) { sleep 10; }
    if ($exp > 0) {
        ender("Expect string/s not found",2,$opt,$pend);
    }
    if ($pend >= $opt->{critical}) { 
        ender("Critical timeout",2,$opt,$pend);
    }
    if ($pend >= $opt->{warning}) {
        ender("Warning timeout",1,$opt,$pend);
    }
    ender("OK Expect sting/s found",0,$opt,$pend);
}

run;
