#!/usr/bin/perl
# ************************************************************************* 
# Copyright (c) 2014, SUSE LLC
# 
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ************************************************************************* 
#
# Web::MREST server executable
#
# -------------------------------------------------------------------------

use 5.014;
use strict;
use warnings;

use App::CELL qw( $log $site );
use Web::MREST;
use Data::Dumper;
use Log::Any::Adapter;
use Module::Runtime qw( is_module_name require_module );
use Plack::Builder;
use Plack::Runner;
use Try::Tiny;
use Web::Machine;
use Web::MREST::Util qw( normalize_filespec );


 
=head1 NAME

mrest - Web::MREST server startup script



=head1 VERSION

Version 0.256

=cut

our $VERSION = '0.256';



=head1 SYNOPSIS

    $ mrest My-Distro My::Module

or 

    $ mrest My::Distro My::Module



=head1 DESCRIPTION

Run this script from the bash prompt to start the server. 



=head1 FUNCTIONS

=cut

sub _welcome_message {
    my $message = "Starting Web::MREST ver. $VERSION";
    print "$message\n";
    $log->notice( $message );
}

sub _parse_argument {
    my ( $distro, $module ) = @ARGV;
    die "You must provide two arguments" unless $distro and $module;

    # for distro, we allow both formats My::Distro and My-Distro
    # distro might be just Foo, or Foo::Bar, or Foo-Bar
    my @tmp_c;
    if ( $distro =~ m/\:/ ) {
        @tmp_c = split( '::', $distro ); 
    } elsif ( $distro =~ m/\-/ ) {
        @tmp_c = split( '-', $distro );
    } else {
        @tmp_c = ( $distro );
    }
    my $app_distro = join( '-', @tmp_c );
    my $app_module = $module;
    die "$app_module is not a module name" unless is_module_name( $app_module );
    print "App distro is $app_distro\n";
    print "App module is $app_module\n";
    my $distro_sharedir;
    my $status;
    try {
        $distro_sharedir = File::ShareDir::dist_dir( $app_distro );
        print "Distro sharedir is $distro_sharedir";
    } catch {
        $status = "Could not find a sharedir for distro $app_distro: $_";
    };
    if ( $status ) {
        die $status;
    }
    return ( $app_distro, $app_module, $distro_sharedir );
}

sub _load_config_params {
    my $app_distro = shift;
    print "Loading configuration parameters\n";
    my $status = Web::MREST::init( distro => $app_distro );
    die $status->text unless $status->ok;
}

sub _set_up_logging {
    print "Setting up logging\n";
    my $log_file = normalize_filespec( $site->MREST_LOG_FILE );
    my $should_reset = $site->MREST_LOG_FILE_RESET;
    unlink $log_file if $should_reset;
    Log::Any::Adapter->set( 'File', $log_file );
    my $message = "Logging to $log_file";
    $log->info( $message );

    if ( ! $site->MREST_APPNAME ) {
        die "Site parameter MREST_APPNAME is undefined - please investigate!";
    }
    $log->init( 
        ident => $site->MREST_APPNAME, 
        debug_mode => ( $site->MREST_DEBUG_MODE || 0 ),
    );
}

sub _init_webmachine {
    my $app_module = shift;
    print "Starting server\n";
    return Web::Machine->new(
        resource => $app_module,
        tracing => 1,
    )->to_app;
}



=head1 MAIN

=cut

_welcome_message();
my ( $app_distro, $app_module, $distro_sharedir ) = _parse_argument();
_load_config_params( $app_distro );  # initializes $site
_set_up_logging();                   # needs $site
my $app = _init_webmachine( $app_module );
my $runner = Plack::Runner->new;

# FIXME: parse @ARGV looking for 'host' and 'port' - if both are present, fine.
# If only one is present, error exit. If neither are present, default to
# DOCHAZKA_HOST and DOCHAZKA_PORT

$runner->parse_options(@ARGV);

#my %options = @{ $runner->{'options'} };
#print "Server host " . ( $options{'host'} || 'undef' ) . "\n";
#print "Server port " . ( $options{'port'} || 'undef' ) . "\n";

$runner->run( 
    builder {
        enable "LogErrors", logger => sub {
            my $args = shift;
            my $level = $args->{'level'};
            my $message = $args->{'message'};
            $log->$level( $message );
        };
#        enable "StackTrace", force => 1;
        enable "Session";
        enable "Static", path => qr{/favicon}, root => $distro_sharedir;
        $app;
    }
);

