./app.psgi


package MGH_Biostat::TravEpi::TRhIP::PSGI;
use Modern::Perl;
use experimental 'switch';
use lib './lib';

use MGH_Biostat::TravEpi::TRhIP::App;
use MGH_Biostat::TravEpi::SimpleRulesBase::SimpleAuthenticator;
use MGH_Biostat::TravEpi::SimpleRulesBase::Logger;
use File::RotateLogs;
use Plack::Response;
use Plack::App::File;
use Plack::Builder;
use Plack::Middleware::EnvObject;

my $NOT_FOUND = [
    404,
    [ 'Content-Type' => 'text/plain; charset=utf-8' ],
    [ 'Not Found' ],
];

# this is a totally stupid way to protect things, but I only want the simplest
# level of protection for a few helper destinations
my $auth = MGH_Biostat::TravEpi::SimpleRulesBase::SimpleAuthenticator->new( 'GTEN', 'xxxx', 'xxxx' );

# create a logger that rotates files
my $rotator = File::RotateLogs->new(
    logfile      => './logs/applog.%Y-%m-%d' . '.' . $$,
    rotationtime => 60 * 60 * 24 * 7,                      # one week
);
my $logger = MGH_Biostat::TravEpi::SimpleRulesBase::Logger->new($rotator);

# by creating the app object externally, we can reload the object
# (and thus reload the templates) without needing to restart the server
my $app_obj = MGH_Biostat::TravEpi::TRhIP::App->new();

my $app = sub {
    my $env = shift;

    given ( $env->{PATH_INFO} ) {
        when ( [ '/', '/index' ] ) {
            return [
                302,
                [ 'Location' => 'trhip' ],
                []
            ];
        }
        when ( [ '/trhip' ] ) {
            return $app_obj->dispatch($env);
        }
        when (qr|cdc-redirect/([a-z-]+)|) {
            my $country = $1;
            my $hash    = $env->{'QUERY_STRING'};    # @WARNING: breach of data encapsulation

            if ( defined($hash) and ( $hash ne '' ) ) {
                $env->{'gten.logger'}->log( $env, $hash, '!na', 'redirect: ' . $country );
            }

            my $cdc_url = "http://wwwnc.cdc.gov/travel/destinations/traveler/none/${country}";
            return [
                302,
                [ 'Location' => $cdc_url ],
                []
            ];
        }
        when ( [ '/dumpapp' ] ) {
            if ( $auth->auth($env) ) {
                use Data::Dump qw/pp/;
                return [
                    200,
                    [ 'Content-Type' => 'text/plain; charset=utf-8' ],
                    [ pp($app_obj) ],
                ];
            }
            else {
                return $auth->unauth();
            }
        }
        when ( [ '/showrules' ] ) {
            if ( $auth->auth($env) ) {
                return $app_obj->showrules($env);
            }
            else {
                return $auth->unauth();
            }
        }

        when ( [ '/showenv' ] ) {
            if ( $auth->auth($env) ) {
                use Data::Dump qw/pp/;
                return [
                    200,
                    [ 'Content-Type' => 'text/plain; charset=utf-8' ],
                    [ pp( \%ENV ) . "\n\n" . pp($env) ],
                ];
            }
            else {
                return $auth->unauth();
            }
        }

        when ( [ '/showlogs' ] ) {
            if ( $auth->auth($env) ) {
                return $app_obj->showlogs($env);
            }
            else {
                return $auth->unauth();
            }
        }

        when ( [ '/stoplogging' ] ) {
            if ( $auth->auth($env) ) {
                my $res = Plack::Response->new(
                    200,
                    [ 'Content-Type' => 'text/plain; charset=utf-8' ],
                    'Logging should be stopped for this computer and browser for 7 days. This may not work in IE.'
                );
                $res->cookies->{'nologging'} = {
                    'value'   => 'stop-logging',
                    'domain'  => 'gten.travel',
                    'path'    => '/trhip',
                    'max-age' => ( 7 * 24 * 60 * 60 ),
                };
                return $res->finalize();
            }
            else {
                return $auth->unauth();
            }
        }
        when ( [ '/startlogging' ] ) {
            if ( $auth->auth($env) ) {
                my $res = Plack::Response->new(
                    200,
                    [ 'Content-Type' => 'text/plain; charset=utf-8' ],
                    'Logging should be re-enabled.'
                );
                $res->cookies->{'nologging'} = {
                    'value'   => 'stop-logging',
                    'domain'  => 'gten.travel',
                    'path'    => '/trhip',
                    'max-age' => 0,
                    'expires' => time - 60,
                };
                return $res->finalize();
            }
            else {
                return $auth->unauth();
            }
        }

        default {
            return $NOT_FOUND;
        }
    }
};

builder {
    # inline middleware to prevent caching
    # based on https://github.com/tokuhirom/Plack-Middleware-NoCache/blob/master/lib/Plack/Middleware/NoCache.pm
    enable sub {
        my $app = shift;
        sub {
            my $env = shift;
            my $res = $app->($env);
            push @{ $res->[ 1 ] }, 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache', 'Expires' => 0;
            return $res;
        };
    };

    enable "EnvObject", 'name' => 'gten.logger', 'object' => $logger;

    mount '/css/trhip.css' => Plack::App::File->new(
        file         => 'public/css/trhip.css',
        content_type => 'text/css'
    )->to_app();
    mount '/images' => Plack::App::File->new( root => 'public/images' )->to_app();
    mount '/js'     => Plack::App::File->new( root => 'public/js' )->to_app();
    mount '/'       => $app;
};