package Test::Harness::Selenium;
use strictures 1;

use File::Find::Rule;
use Socialtext::WikiFixture::Selenese;
use HTML::TableExtract;
use IO::All;
use Alien::SeleniumRC;
use LWP::Simple;

use Test::More;
BEGIN {
  package Test::Builder;

  use Class::Method::Modifiers;
  use ExtUtils::MakeMaker qw(prompt);

  if (!$ENV{AUTOMATED_TESTING}) {
    around ok => sub {
      my ($orig, $self) = (shift, shift);
      my $res = $self->$orig(@_);
      unless ($res) {
        if ('y' eq prompt "Well that didn't work, did it. Bail out?", 'y') {
          exit 255;
        }
      }
      return $res;
    };
  }
}

sub new {
  my ($class, $self) = @_;
  if($self->{xvnc}) {
    $ENV{DISPLAY} = $self->{xvnc};
    my $xvnc_pid = fork();
    if(!defined $xvnc_pid) {
      die "couldn't fork xvnc: $!";
    }
    elsif($xvnc_pid) {
      $self->{xvnc_pid} = $xvnc_pid;
    }
    else {
      exec("vncserver", $self->{xvnc});
    }
  }
  bless $self, $class;
}

sub start_server {
  my($self) = @_;
  $self->{server_pid} = fork();
  if(!defined $self->{server_pid}) {
    die "can't fork: $!";
  }
  if($self->{server_pid} > 0) {
    my $tries = 0;
    while($tries < 5) {
      eval {
        $self->{src} = Socialtext::WikiFixture::Selenese->new(
          host => $self->{host},
          port => $self->{port},
          browser => $self->{browser},
          browser_url => $self->{browser_url},
        );
      };
      $tries++;
      if(!defined $self->{src}) {
        sleep 10;
      }
      else {
        last;
      }
    }
    die "timed out waiting for selenium server to start" if $tries == 5;
  }
  elsif($self->{server_pid} == 0) {
    # muttermutter, can't specify a host for selenium
    exec("$^X -MAlien::SeleniumRC -e 'Alien::SeleniumRC::start(q{-port $self->{port}})'");
  }
}

sub stop_server {
  my($self) = @_;
  # okay, we're done, kill the server.
  get("http://localhost:$self->{port}/selenium-server/driver/?cmd=shutDownSeleniumServer");
  delete $self->{src};
  wait;
}

sub test_directory {
  my ($self, $dir) = @_;
  my @tests = File::Find::Rule->file()->name('*.html')->in($dir);
  for my $test (@tests) {
    $self->start_server;
    $self->run_tests_for($test);
    $self->stop_server;
  }
}

sub run_tests_for {
  my ($self, $html_file) = @_;
  my $rows = $self->get_rows_for($html_file);
  $self->{src}->run_test_table($rows);
}

my $te = HTML::TableExtract->new;
sub get_rows_for {
  my ($self, $html_file) = @_;
  my $html = io($html_file)->all;
  $te->parse($html);
  my $table = ($te->tables)[0];
  my @rows = map {
    [ map { (!defined $_ or $_ eq "\240") ? () : $_ } @$_ ]
  } grep { defined $_->[1] } $table->rows;
  return \@rows;
}

sub DESTROY {
  my($self) = @_;
  if(exists $self->{xvnc_pid}) {
    kill("KILL", $self->{xvnc_pid});
  }
}

1;
