#!/usr/bin/env perl

use strict;
use warnings;
use Path::Tiny qw( path );
use Getopt::Long qw( GetOptions );
use URI;
use URI::Escape qw( uri_unescape );
use JSON::PP qw( encode_json decode_json );
use HTTP::Server::PSGI;
use Plack::Builder;
use Plack::App::Directory;


my $daemon = 0;
my $kill   = 0;
my $host   = 'localhost';

GetOptions(
  "d"      => \$daemon,
  "k"      => \$kill,
  "host=s" => \$host,
);

my $bindir    = path(__FILE__)->parent->absolute;
my $distdir   = $bindir->parent->parent;

my $config_file = $bindir->child('httpd.json');

if(-r $config_file)
{
  my $config = decode_json($config_file->slurp);
  my $pid = $config->{pid};
  if(defined $pid)
  {
    kill 'KILL', $pid;
  }
}

exit if $kill;

if($daemon)
{
  require Proc::Daemon;
  my $daemon = Proc::Daemon->new(
    child_STDOUT => $bindir->child('httpd.log')->stringify,
    child_STDERR => $bindir->child('httpd.log')->stringify,
  );
  $daemon->Init;
}

my $url = URI->new('http://localhost/corpus/dist/');
$url->host($host);
$url->port(do {
  require IO::Socket::INET;
  IO::Socket::INET->new(Listen => 5, LocalAddr => "127.0.0.1")->sockport;
});

my %config = (
  root => $distdir->child('corpus/dist')->stringify,
  pid  => $$,
  url => $url->as_string,
);
$config_file->spew(encode_json(\%config));

my $app = builder {
  mount '/corpus/dist/test1/' => sub {
    my $env = shift;
    my %headers;
    foreach my $key (keys %$env)
    {
      next unless $key =~ /^HTTP_(.*)$/;
      my $name = join '-', map { ucfirst $_ }map { lc $_ } split /_/, $1;
      $headers{$name} = $env->{$key};
    }
    my $uri = URI->new($env->{'psgi.url_scheme'} . '://' . $env->{SERVER_NAME} . uri_unescape($env->{REQUEST_URI}), $env->{'psgi.url_scheme'});
    $uri->port($env->{SERVER_PORT});

    my %query;
    my @query = $uri->query_form;
    while(@query)
    {
      my $key = shift @query;
      my $value = shift @query;
      push @{ $query{$key} }, $value;
    }

    return [
      '200',
      [ 'Content-Type' => 'text/plain; charset=UTF-8' ],
      [ encode_json( { headers => \%headers, url => { scheme => $uri->scheme, host => $uri->host, port => $uri->port, path => $uri->path, query => \%query } } ) ],
    ];
  };
  mount '/corpus/dist/about.json' => sub {
    my $env = shift;
    return [
      '200',
      [ 'Content-Type' => 'application/json' ],
      [ encode_json( { ident => 'AB Test HTTPd' } ) ],
    ];
  };
  mount '/' => Plack::App::Directory->new({ root => $distdir->stringify })->to_app;
};

my $server = HTTP::Server::PSGI->new(
  host => $url->host,
  port => $url->port,
);

$server->run($app);
