#!/usr/bin/env perl

use lib::abs '../perl5/lib/perl5';
use lib::abs '.';

use common::sense;

use Data::Dumper;
use Cwd 'realpath';
use File::Basename qw/dirname basename/;
use File::Copy;
use Getopt::Long;
use open qw/:std :utf8/;
use POSIX 'uname';
use Template;

use Utils;

sub print_usage {
    print <<EOF;
$0 - processing config templates with host resolving

Usage: $0
          --hosts /path/to/conf --input /path/to/template
         [--host hostname]     [--output /path/to/result]

Options:
    --help -h       Print this help
    --hosts         File path with hosts configuration
    --input  -i     Input template path
    --output -o     Output file path, by default print to stdout
    --host          Choose host by specified name
                    Name may be the full hostname, it's prefix and it's alias
                    For example, this names are specify to the same host:
                      'passport-u2.yandex.net', 'passport-u2' and 'u2'
                    If not defined, it will be detect automatically

Example:
    conf/configurator \
      --hosts  conf/hosts \
      --host   i1 \
      --input  conf/templates/passport.conf.tt \
      --output etc/conf/passport.conf
EOF
}


###
# Получение и проверка входящих параметров

print 'Params: ', join(' ', @ARGV), "\n";

my %opt;

GetOptions(\%opt,
    'hosts=s',
    'host=s',
    'input|i=s',
    'output|o=s',
    'stash|s=s%',
    'help|h',
);

if ($opt{help}) {
    print_usage();
    exit 1;
}

die "--hosts is required"
  unless $opt{hosts};

die "--input is required"
  unless $opt{input};

die "hosts configuration '$opt{hosts}' isn't exist"
  unless -e $opt{hosts};

die "input template '$opt{template}' isn't exist"
  unless -e $opt{input};

delete $opt{output}
  if $opt{output} eq '-';


###
# Определение и поиск хоста в конфиге

my $hosts_path = realpath($opt{hosts});
print "Hosts: $hosts_path\n";
my $host = Utils->get_host(
    hosts => $hosts_path,
    host  => $opt{host},
);

###
# Дебаг
print "Host: $host->{name}\n";
print "Input: $opt{input}\n";
print "Output: ", $opt{output} || '<stdout>', "\n";


###
# Прогон через шаблонизатор

my $stash = {
    %{ $host->{stash} },
    %{ $opt{stash}    },
};

my $tt = Template->new({
    INCLUDE_PATH => dirname($opt{input}),
    CACHE_SIZE   => 0,
    UNICODE      => 1,
    ENCODING     => 'utf-8',
});

my $dest = $opt{output} ? "$opt{output}.tmp" : \*STDOUT;

$tt->process(basename($opt{input}), $stash, $dest, binmode => ':utf8')
  or die $tt->error, "\n";


###
# Конечное перемещение результата
if ($opt{output}) {
    move($dest => $opt{output})
      or die "can't move temporary outfile '$dest' to destination outfile '$opt{output}': $!\n";
}
