#!/usr/bin/perl
use strict;
use warnings;
use English;
use Carp;
use POSIX qw( setsid );
use IO::Socket;
use Hash::Merge qw(merge);
use Template;
use YAML::XS qw(LoadFile);
use Clone 'clone';
use Getopt::Long;

my $quiet = 0;

GetOptions("q|quiet" => \$quiet);

my $server_port = get_server_port();

daemonize();

handle_connections( $server_port, $quiet );

exit;

sub daemonize {
    chdir '/'                      or croak "Can't chdir to /: $ERRNO";
    open(STDIN,  '<', '/dev/null') or croak "Can't read /dev/null: $ERRNO";
    open(STDOUT, '>', '/dev/null') or croak "Can't write to /dev/null: $ERRNO";
    defined(my $pid = fork)        or croak "Can't fork: $ERRNO";
    exit if $pid;
    setsid                         or croak "Can't start a new session: $ERRNO";
    open(STDERR, '>&', \*STDOUT)   or croak "Can't dup stdout: $ERRNO";
    return;
}

sub get_server_port {
    my $server = IO::Socket::INET->new(
        'Proto'     => 'tcp',
        'LocalAddr' => 'localhost',
        'Listen'    => SOMAXCONN,
        'Reuse'     => 1,
    );
    die "Error: can't setup tt2-daemon!\n$EVAL_ERROR\n$ERRNO\n" unless $server;

    binmode $server => ":encoding(utf8)";

    my $NGCP_PORTFILE = $ENV{'NGCP_PORTFILE'} //= '/var/run/ngcpcfg.port';
    if (open (my $portfile, '>', "$NGCP_PORTFILE")) {
        print $portfile $server->sockport();
        close ($portfile);
        return $server;
    } else {
        die "Can't write to $NGCP_PORTFILE\n";
    }
}

sub handle_connections {
    my $port = shift;
    my $quiet = shift;
    my $config = {};
    my %loaded_ymls = ();

    while ( my $client = $port->accept() ) {
    chomp ( my $input = <$client> );

    my $tt = Template->new({ ABSOLUTE => 1, RELATIVE => 1, EVAL_PERL => 1 });
    my @ARGV = split(' ', $input) or
        print $client "Usage: echo '<template> [<config.yml> [<another.yml>]]' | netcat localhost 42042 \n";
    my $template =  shift(@ARGV);

    if (scalar @ARGV) {
        foreach my $file (@ARGV)
        {
            next if(exists $loaded_ymls{$file});
            $loaded_ymls{$file} = undef;
            print $client "Loading $file in memory:" unless $quiet;
            my $hm = Hash::Merge->new('RIGHT_PRECEDENT');
            $config = $hm->merge( $config, LoadFile($file));
            print $client " OK \n" unless $quiet;
        };
    };

    open my $fh, '<', $template or
        print $client "Unable to open file '$template' for reading: $ERRNO\n";
    $tt->process($fh, clone($config), $client) or print $client $tt->error;
    close $fh;

    close $client;
    }

    return;
}
