#!/usr/bin/env perl

use strict;
use warnings;
use Mojolicious::Lite;
use Mojo::JSON qw(decode_json);
use Net::Statsite::Client;
use Mojo::File qw(path);
use File::Spec;
use File::stat;
use Log::Dispatch;
use MojoX::Log::Dispatch::Simple;

use Stor;
use RmqPublishFactory;

$ENV{MOJO_MAX_MESSAGE_SIZE} = 524288000;    #the size of message: 500 MB

my $cfg      = load_config();
my $statsite = Net::Statsite::Client->new(%{ $cfg->{statsite} });

my $logger = MojoX::Log::Dispatch::Simple->new(
    dispatch => Log::Dispatch->new(outputs => $cfg->{log}),
    level    => 'debug'
);

my $rmq_factory = RmqPublishFactory->new(
    uri => $cfg->{rabbitmq_uri},
    log => $logger,
);

$rmq_factory->create_mojo_heartbeat();

my $stor = Stor->new(
    storage_pairs        => $cfg->{storage_pairs},
    statsite             => $statsite,
    basic_auth           => $cfg->{basic_auth},
    s3_credentials       => $cfg->{s3_credentials},
    s3_enabled           => $cfg->{s3_enabled},
    writable_pairs_regex => $cfg->{writable_pairs_regex} // '.*',
    rmq_publish_code     => $rmq_factory->create(),
);

app->plugin(
    CHI => {
        default => {
            driver   => 'Memcached::Fast',
            servers  => $cfg->{memcached_servers},
            l1_cache => { driver => 'Memory', global => 1, max_size => 1024 * 1024 }
        }
    }
);

app->config(hypnotoad => { clients => $ENV{HYPNOTOAD_CLIENTS} // 100 });
app->log($logger);

start_cleanup_tempdir_task();

get '/'       => sub { $stor->about(@_) };
get '/status' => sub { $stor->status(@_) };
get '/:sha'   => sub { $stor->get(@_) };
post '/:sha'  => sub { $stor->post(@_) };

app->secrets([ $cfg->{secret} ]);
app->start;

sub load_config {
    die 'CONFIG_FILE environment variable not set'
      if !defined $ENV{CONFIG_FILE};

    return decode_json(path($ENV{CONFIG_FILE})->slurp());
}

# cleanup old temp files
sub start_cleanup_tempdir_task {
    my $cleanup_tempdir_period = $cfg->{cleanup_tempdir_period} // 60 * 30;    #default 30m
    Mojo::IOLoop->recurring(
        $cleanup_tempdir_period => sub {
            path(File::Spec->tmpdir)
              ->list()
              ->grep(sub { $_->basename =~ /^mojo\.tmp/ })
              ->grep(sub { stat($_)->mtime < (time - $cleanup_tempdir_period)})
              ->each(sub { $_->remove_tree });
        }
    );
}

