#!/usr/bin/env perl
use strict;
use warnings;
use File::Basename qw( basename );
use Cwd qw( abs_path );

$ENV{HOME}                       ||= '__NO_HOME__';
$ENV{MOJO_CONFIG}                ||= '';
$ENV{TOADFARM_APPLICATION_CLASS} ||= 'Toadfarm';
$ENV{TOADFARM_SILENT}            ||= 0;

sub help {
  return <<"HELP";
usage: $0 [OPTIONS] [CONFIG_FILE]

  # Show manual page
  toadfarm --man

  # Start or hot reload
  toadfarm path/to/apps.conf

  # Custom application
  toadfarm -a /path/to/myapp.pl path/to/mojo.conf

Default config file will be "\$HOME/.toadfarm/\$app.conf", where
\$app is specified by "-a".

  toadfarm -a toadfarm == toadfarm \$HOME/.toadfarm/toadfarm.conf"

These options are available:
  -a <path>          Custom application (other than toadfarm)
  -f, --foreground   Keep manager process in foreground.
  -h, --help         Show this message.
      --man          Show manual
      --start        Only start - no hot reload
  -s, --stop         Stop server gracefully.
  -t, --test         Test application and exit.

HELP
}

sub read_pid {
  my $pid_file = $_[0]->{hypnotoad}{pid_file} or die "Cannot start without hypnotoad => pid_file in config file\n";

  warn "pid_file=$pid_file\n" if $ENV{TOADFARM_SILENT} == -1;

  return 0 unless -s $pid_file;
  return eval {
    open my $PID, $pid_file or die "Could not read $pid_file: $!";
    scalar(<$PID>) =~ /(\d+)/g ? $1 : 0;
  };
}

sub start {
  $ENV{MOJO_CONFIG} or die "Path to config file is required as input\n";
  require Mojolicious::Plugin::Config;
  require Mojolicious;
  my $config = Mojolicious::Plugin::Config->new->load($ENV{MOJO_CONFIG}, {}, Mojolicious->new);
  my $pid = read_pid($config);

  warn "pid=$pid\n" if $ENV{TOADFARM_SILENT} == -1;

  if ($pid and kill 0, $pid) {
    print "$ENV{HYPNOTOAD_APP} - running ($pid)\n" unless $ENV{TOADFARM_SILENT};
  }
  else {
    print "$ENV{HYPNOTOAD_APP} - starting\n" unless $ENV{TOADFARM_SILENT};
    exec hypnotoad => @_ => $ENV{HYPNOTOAD_APP};
  }

  return 0;
}

unless ($ENV{MOJO_APP_LOADER}) {
  $ENV{HYPNOTOAD_APP} = __FILE__;
  my ($start, @args);

  while (@ARGV) {
    my $arg = shift @ARGV;
    if (-r $arg) {
      $ENV{MOJO_CONFIG} = $arg;
    }
    elsif (-r "$ENV{HOME}/.toadfarm/$arg") {
      $ENV{MOJO_CONFIG} = "$ENV{HOME}/.toadfarm/$arg";
    }
    elsif ($arg eq '-a') {
      $ENV{HYPNOTOAD_APP} = shift @ARGV or die "Usage: -a <app> ...\n";

      if (!-x $ENV{HYPNOTOAD_APP}) {
        require File::Spec;
        for my $p (File::Spec->path) {
          next unless -x "$p/$ENV{HYPNOTOAD_APP}";
          $ENV{HYPNOTOAD_APP} = "$p/$ENV{HYPNOTOAD_APP}";
          last;
        }
      }

      if (-x $ENV{HYPNOTOAD_APP}) {
        $ENV{MOJO_CONFIG} ||= sprintf '%s/.toadfarm/%s.conf', $ENV{HOME}, basename $ENV{HYPNOTOAD_APP};
      }
      else {
        $ENV{TOADFARM_APPLICATION_CLASS} = $ENV{HYPNOTOAD_APP};
        $ENV{HYPNOTOAD_APP} =~ s/::/-/g;
        $ENV{MOJO_CONFIG} ||= sprintf '%s/.toadfarm/%s.conf', $ENV{HOME}, lc $ENV{HYPNOTOAD_APP};
        $ENV{HYPNOTOAD_APP} = __FILE__;
      }
    }
    elsif ($arg eq '--man') {
      exec perldoc => 'Toadfarm';
    }
    elsif ($arg eq '--start') {
      $start = 1;
    }
    else {
      push @args, $arg;
    }
  }

  if ($ENV{MOJO_CONFIG}) {
    $ENV{MOJO_CONFIG} = abs_path $ENV{MOJO_CONFIG};
    warn "MOJO_CONFIG=$ENV{MOJO_CONFIG} hypnotoad @args $ENV{HYPNOTOAD_APP}\n" if $ENV{TOADFARM_SILENT} == -1;
  }

  exit start(@args) if $start;
  exec hypnotoad => @args => $ENV{HYPNOTOAD_APP} if $ENV{MOJO_CONFIG};
  print help();
  exit 0;
}

# Start command line interface for application
require Mojolicious::Commands;
Mojolicious::Commands->start_app($ENV{TOADFARM_APPLICATION_CLASS});
