#!/usr/bin/perl
use File::Copy;
use File::Path;
use File::Basename;
use POSIX qw(strftime);

%subst = ( );
@subst_files = ( "private/config.py" );
sub subst {
    my $root = shift(@_);
    for $f ( @subst_files ) {
        my $path = "$root/$f";
        open( DST, "< $path");
        @dest = <DST>;
        close(DST);
        open( DST, "> $path");
        foreach ( @dest ) {
            foreach $k ( keys %subst ) {
                s|$k|$subst{$k}|;
                print DST $_;
            }
        }
        close( DST );
    }
}

sub rsync {
    my ($from, $to) = @_;
    my $cmd;
    if ( -f $from || (-d $from && $from =~ m|/$|) ) {
        $cmd = "rsync -aq $from $to";
    } else {
         $cmd = "rsync -aq $from/ $to";
    }
    print("\t$cmd\n");
    open( RSYNC, "$cmd 2>&1 |" );
    for ( <RSYNC> ) { print "\t>\t$_" }
    close( RSYNC );
}

sub get_proto {
    my $path = shift(@_);
    my $name = basename($path);
    my $dir = dirname($path);
    if ( ! -f $path ) { die "protobuf spec, '$name', is not a file" }
    return ( $dir, $name );
}

$prefix = "";
$app_path = "";
$protoc = "";
$proto_shutdown = "";
$proto_ping = "";
$proto_img = "";
$build_number = "";
foreach ( @ARGV ) {
    m|^BUILD=$| && ( next );
    m|^prefix=(.*)| && ( $prefix = $1, next );
    m|^app=(.*)| && ( $app_path = $1, next );
    m|^protoc=(.*)| && ( $protoc = $1, next );
    m|^shutdown=(.*)| && ( $proto_shutdown = $1, next );
    m|^ping=(.*)| && ( $proto_ping = $1, next );
    m|^img=(.*)| && ( $proto_img = $1, next );
    m|^BUILD=(\d+.\d+.\d+)$| && ( $build_number = $1, next );
    if ( m|^BUILD=| ) { die "build number must be a number" }
    die "unknown option: $_";
}

if ( ! $prefix ) { die "no prefix specified" };
if ( ! -d $prefix) { mkpath($prefix) }
if ( ! -d $prefix) { die "cannot create prefix" }
if ( ! $app_path )  { die "no prefix specified" };
$app_name = basename($app_path);
if ( $^O eq "darwin" ) {
    if ( ! -d $app_path ) { die "app directory does not exist (or is not a directory)" }
    my( $filename, $dirs, $suffix ) = fileparse( $app_path, ".app" );
    $app_exe = "__bin__/$app_name/Contents/MacOS/$filename";
    $subst{'@APP@'} = $app_exe;
} else {
    if ( ! -f $app_path ) { die "app image does not exist" }
    $app_exe = "__bin__/$app_name";
    $subst{'@APP@'} = $app_exe;
}
if ( ! $protoc ) { die "no prefix specified" };
if ( ! -x $protoc ) { die "cannot execute proto compiler" }
if ( ! $proto_shutdown ) { die "no shutdown proto specified" };
( $proto_shutdown_dir, $proto_shutdown_name ) = get_proto($proto_shutdown);
if ( ! $proto_img ) { die "no img proto specified" };
( $proto_img_dir, $proto_img_name ) = get_proto($proto_img);
if ( ! $proto_ping ) { die "no ping proto specified" };
( $proto_ping_dir, $proto_ping_name ) = get_proto($proto_ping);

open( $xml_query, "python3 -m casatools --compiler-xml 2> /dev/null |" );
chomp( $xml_compiler = <$xml_query> );
close( $xml_query );

@xml_files = ( 'casa-source/casa5/gcwrap/tasks/imview.xml',
               'casa-source/casa5/gcwrap/tasks/msview.xml' );
print("generating task wrappers...\n");
open( $xml, "$xml_compiler -task output-task=$prefix @xml_files 2>&1 |" ) or die "could not compile task xml files";
foreach ( <$xml> ) {
    print("\t<xml> $_");
}
close($xml);
print("generating gotask wrappers...\n");
mkpath("$prefix/gotasks");
$stamp = strftime("%F %H:%M:%S", localtime);
open( $init, "> $prefix/gotasks/__init__.py" );
print $init "## generated by casaviewer/generate-module $stamp\n";
close( $init );
open( $xml, "$xml_compiler -gotask gotask-imp-module=casaviewer output-gotask=$prefix/gotasks @xml_files 2>&1 |" ) or die "could not compile task xml files, into gotask wrappers";
foreach ( <$xml> ) {
    print("\t<xml> $_");
}
close($xml);

rsync("src/module", $prefix);
subst($prefix);
if ( ! -d "$prefix/private" ) { mkpath("$prefix/private") }
$cmd = "$protoc -I$proto_img_dir --python_out=$prefix/private --grpc_out=$prefix/private $proto_img_name";
print(">> $cmd\n");
open( PROTOC, "$cmd 2>&1 |" );
foreach ( <PROTOC> ) { print( "\t$_" ) }
close(PROTOC);
$cmd = "$protoc -I$proto_shutdown_dir --python_out=$prefix/private --grpc_out=$prefix/private $proto_shutdown_name";
print(">> $cmd\n");
open( PROTOC, "$cmd 2>&1 |" );
foreach ( <PROTOC> ) { print( "\t$_" ) }
close(PROTOC);
$cmd = "$protoc -I$proto_ping_dir --python_out=$prefix/private --grpc_out=$prefix/private $proto_ping_name";
print(">> $cmd\n");
open( PROTOC, "$cmd 2>&1 |" );
foreach ( <PROTOC> ) { print( "\t$_" ) }
close(PROTOC);
mkpath("$prefix/__bin__");
rsync( $app_path, "$prefix/__bin__/$app_name" );
rsync("src/setup.py","$prefix/..");

chdir("$prefix/..");
if ( $build_number ) {
    exec ( './setup.py', 'bdist_wheel', "--build=$build_number" ) or die "could not build wheel: $!";
} else {
    exec ( './setup.py', 'bdist_wheel' ) or die "could not build wheel: $!";
}