#!/usr/bin/perl
use strict;
use warnings;

use File::Copy;
use File::Path;
use File::Find;
use File::Basename;
use lib ( dirname($0) );
use Qtopia::Paths;
use Qtopia::Vars;
use Qtopia::File;
use Qtopia::Opt;
use Carp;
#perl2exe_include Carp::Heavy
$Carp::CarpLevel = 1;

Qtopia::Paths::get_paths();

# Windows depot builds use the perl scripts directly rather than the compiled code
if ( $isWindows ) {
    check_script($0, "$depotpath/src/build/bin", $ARGV[0]);
}

Qtopia::Opt::read_config_cache();

use constant DEBUG => 0;

my $print_usage = 0;

# This list must match what is in the for loop below!
my (  $make, $format, $working_path, $arch, $project_root, $languages,
      $pkg_path, $srcdir, $out_pwd,
      $pkg_name, $pkg_desc, $domain, $pkg_deps, $pkg_multi, $pkg_version, $pkg_trust,
      $pkg_license, $pkg_maintainer, $pkg_targets, $pkg_quicklaunch,
      $split_i18n ) = ();

for ( $make, $format, $working_path, $arch, $project_root, $languages,
      $pkg_path, $srcdir, $out_pwd,
      $pkg_name, $pkg_desc, $domain, $pkg_deps, $pkg_multi, $pkg_version, $pkg_trust,
      $pkg_license, $pkg_maintainer, $pkg_targets, $pkg_quicklaunch,
      $split_i18n ) {
    $_ = shift(@ARGV);
    if ( !defined($_) ) {
        $print_usage = 1;
        last;
    }
}

# Defaults
if ( !$format ) { $format = "qpk"; }
if ( ! $split_i18n ) {
    if ( $format eq "qpk" ) {
        $split_i18n = 0;
    } else {
        $split_i18n = 1;
    }
}
my $install = "install";
if ( opt("qbuild") ) {
    $install = "image";
    if ( -e $make ) {
        $make = "$make -script";
    } else {
        $make = "$SDKROOT/bin/qbuild -script";
    }
}

# Clean this up (the build system makes a mess of the values when catenating multiple domain sets)
if ( $domain ) {
    my %tmp;
    map { $tmp{$_}++ } split(/[, ]/, $domain);
    $domain = join(",", keys(%tmp));
}

DEBUG and print <<DUMP_END;
    Make:          $make
    Format:        $format
    Work path:     $working_path
    Arch:          $arch
    Project root:  $project_root
    Languages:     $languages
    Package path:  $pkg_path
    Source dir:    $srcdir
    Out word dir:  $out_pwd
    Package name:  $pkg_name
    Package desc:  $pkg_desc
    SXE domain:    $domain
    Package deps:  $pkg_deps
    Package multi: $pkg_multi
    Package ver:   $pkg_version
    Trust:         $pkg_trust
    License:       $pkg_license
    Maintainer:    $pkg_maintainer
    Targets:       $pkg_targets
    Quicklaunch:   $pkg_quicklaunch
DUMP_END

if ( $print_usage ) {
    usage();
}

if ( $format eq "qpk" && $pkg_quicklaunch ) {
    die "ERROR: You must remove CONFIG+=quicklaunch and rebuild in order to create a package.\n";
}

my $data_path = "$working_path/data";
my $prefix = "$data_path";
my $instprefix = "$prefix";

# These formats have the full prefix path encoded (ie. they're extracted to the root directory)
if ( $format eq "rpm" || $format eq "deb" || $format eq "ipk" ) {
    $instprefix .= opt("prefix");
}

rmrf($working_path);
mkpath($data_path);

# IPK variables
my $deb_version = "2.0";
my $control_path;
if ( $format eq "ipk" || $format eq "deb" ) {
    $control_path = "$working_path/control";
} else {
    $control_path = "$working_path";
}
my $control_file = "$control_path/control";
my $tar_options = "-cz --owner=0 --group=0"; #"--remove-files -cz --owner=0 --group=0";
my $ar_options = "crf";

my @scripts;
if ( $format eq "ipk" || $format eq "deb" ) {
    @scripts = qw(preinst postinst prerm postrm);
}

print "\n\nInstalling files...\n\n";

for my $dir ( split(/\s+/, $pkg_multi) ) {
    $dir =~ s/^s+//;
    $dir =~ s/s+$//;
    if ( opt("qbuild") ) {
        next unless ( $dir && -d "$dir" );
        chdir "$dir" or die "chdir $dir : $!";
    } else {
        next unless ( $dir && -d "$project_root/$dir" );
        chdir "$project_root/$dir" or die "chdir $project_root/$dir : $!";
    }
    run("$make $install IMAGE=$instprefix");
}
for my $target ( split(/\s+/, $pkg_targets) ) {
    chdir $out_pwd;
    run("$make $target IMAGE=$instprefix");
}

print "\n\nCreating packages...\n\n";

if ( $split_i18n ) {
    for my $lang ( split(/\s+/, $languages) ) {
        my $suffix = "_i18n_$lang";
        my $deps = $pkg_name;
        # Add a dependency on the server's i18n package (it has/used to have the global translations)
        if ( $pkg_name =~ /^qpe-/ && $pkg_name ne "qpe-taskbar" ) {
            $pkg_deps .= " qpe-taskbar_i18n_$lang";
        }
        my $path = "$instprefix/i18n/$lang";
        mkdir "$instprefix/i18n" unless ( -d "$instprefix/i18n" );
        mkdir $path unless ( -d $path );
        make_pkg($suffix, $deps, $path);
    }

    # remove i18n stuff so it doesn't get in the regular package
    if ( -d "$instprefix/i18n" ) {
        rmrf("$instprefix/i18n");
    }
}

make_pkg("", $pkg_deps, $prefix);
if ( DEBUG ) {
    print "Working directory is $working_path\n";
} else {
    rmrf($working_path);
}
print "\n\n";


exit 0;


sub usage
{
    print "Usage:  qbuild packages [FORMAT=qpk|ipk|rpm|deb]\n";
    exit 2;
}


sub make_pkg
{
    my ( $suffix, $deps, $path ) = @_;
    if ( ! -d $path ) {
        carp "$path directory not found";
        return;
    }
    chdir $data_path;
    if ( $path eq $data_path ) {
        if ( $format eq "rpm" ) {
            $path = "/";
        } else {
            $path = ".";
        }
    } else {
        $path =~ s,^\Q$data_path\E/,,;
    }

    my @files = ();
    find(sub {
            my $file = $File::Find::name;
            if ( -f $file || -l $file ) {
                $file =~ s/^\Q$data_path\E\///;
                push(@files, $file);
            }
        }, "$data_path/$path");

    if ( !@files ) {
        return;
    }

    if ( $format eq "ipk" || $format eq "qpk" || $format eq "deb" ) {
        mkpath($control_path);
        # WTF does this do?
        #echo "${p.deps}" | sed 's/\( [^(]\)/,\1/g' >> ${CONTROL_PATH}/DEPS

        my $scripts = "";
        for ( @scripts ) {
            my $script = "$srcdir/$pkg_name.$_";
            if ( -e $script ) {
                $scripts .= " ./$_";
                copy("$script", "$working_path/$_");
            }
        }

        open OUT, ">$control_file" or die "Can't write $control_file";
        print OUT "Package: $pkg_name$suffix\n";
        print OUT "Description: $pkg_desc\n";
        print OUT "Maintainer: $pkg_maintainer\n";
        print OUT "License: $pkg_license\n";
        print OUT "Version: $pkg_version\n";
        if ( $format eq "qpk" ) {
            print OUT "Trust: $pkg_trust\n";
        }
        print OUT "Architecture: $arch\n";
        if ( $format eq "ipk" || $format eq "deb" ) {
            print OUT "Depends: $deps\n";
        }
        if ( $format eq "qpk" ) {
            print OUT "Domain: $domain\n";
            print OUT "QtopiaVersion: ".get_compat_vers()."\n";
            print OUT "Devices: ".get_compat_dev()."\n";
            print OUT "Type: ".(opt("sxe")?"sxe-only":"generic")."\n"; 
        }
        print OUT "File-Count: ".`expr \`(du -ah $path | wc -l)\` - 1`;
        print OUT "Installed-Size: ".`du -sb $path | awk '{print \$1}'`;
        if ( $format eq "ipk" ) {
            print OUT "Filename: "."${pkg_name}${suffix}_${pkg_version}_$arch.$format"."\n";
            print OUT "Source:"."\n";
            print OUT "Homepage:"."\n";
            print OUT "Priority: required"."\n";
            print OUT "Section: qt-extended"."\n";
	    }
        close OUT;

        if ( DEBUG ) {
            print "\n\nControl file\n";
            print "------------8< ---------------------------\n";
            system("cat", $control_file);
            print "------------8< ---------------------------\n";
        }
        my $cmd = "tar $tar_options -f $pkg_path/${pkg_name}${suffix}_${pkg_version}_$arch.$format ";
        if ( $format eq "ipk" || $format eq "deb"  ) {
            $cmd = "ar $ar_options $pkg_path/${pkg_name}${suffix}_${pkg_version}_$arch.$format ";
        }

        if ( $format eq "ipk" || $format eq "deb"  ) {
            open OUT, ">$working_path/debian-binary" or die "Can't write $working_path/debian-binary";
            print OUT "2.0\n";
            close OUT;

            chdir $control_path;
            run("tar $tar_options -f $working_path/control.tar.gz ./control");

            $cmd .= "./debian-binary ./control.tar.gz ./data.tar.gz $scripts";
        } else {
            $cmd .= "./control ./data.tar.gz";
        }
        chdir $data_path;
        run("tar $tar_options -f $working_path/data.tar.gz $path");

        mkpath($pkg_path);
        chdir $working_path;
        run("$cmd");
        print "Created $pkg_path/${pkg_name}${suffix}_${pkg_version}_$arch.$format\n";
    } elsif ( $format eq "rpm" ) {
        my $spec = "$working_path/$pkg_name.spec";
        my $ver;
        my $rel;
        if ( $pkg_version =~ /-/ ) {
            ( $ver ) = ( $pkg_version =~ /(.*)-/ );
            ( $rel ) = ( $pkg_version =~ /-(.*)/ );
        } else {
            $ver = $pkg_version;
            $rel = "1";
        }
        open OUT, ">$spec" or die "Can't write $spec";
        print OUT "Summary: $pkg_desc\n";
        print OUT "Name: $pkg_name$suffix\n";
        print OUT "Group: none\n";
        print OUT "License: $pkg_license\n";
        print OUT "Version: $ver\n";
        print OUT "Release: $rel\n";
        print OUT "%description\n$pkg_desc\n";
        print OUT "%files\n";
        print OUT "%defattr(-,root,root)\n".join("\n", @files)."\n";
        close OUT;
        DEBUG and print "Running rpmbuild -bb --root=$data_path --target=$arch-unknown-linux $spec\n";
        my $output = `rpmbuild -bb --root=$data_path --target=$arch-unknown-linux $spec`;
        my $rpm;
        for ( split(/\n/, $output) ) {
            if ( /Wrote: (.*)/ ) {
                $rpm = $1;
                last;
            }
        }
        if ( $rpm ) {
            copy($rpm, "$pkg_path/".basename($rpm));
            unlink $rpm;
            print "Created $pkg_path/".basename($rpm)."\n";
        }
    }
}

sub get_compat_vers
{
    my $verfile = resolveHeader("$SDKROOT/include/qtopiabase/version.h");
    my $vers = "";
    open IN, $verfile or die "Can't read $verfile";
    while ( defined($_ = <IN>) ) {
        if ( /QTOPIA_COMPATIBLE_VERSIONS\s+"(.*)"/ ) {
            $vers = $1;
            last;
        }
    }
    close IN;
    if ( $vers eq "" ) {
        die "ERROR: Couldn't read binary compatible versions from ".fixpath($verfile)."\n";
    }
    return $vers; 
}

sub get_compat_dev
{
    # this should resolve to the device specific custom.h
    my $customHeader = resolveHeader("$SDKROOT/include/qtopiabase/custom-qtopia.h");
    my $devices = "";
    if ( open(IN, $customHeader) ) {
        while ( defined($_ = <IN>) ) {
            if ( /QTOPIA_COMPATIBLE_DEVICES\s+"(.*)"/ ) {
                $devices = $1;
                last;
            }
        }
        close IN;
        if ( $devices eq "" ) {
            print "Warning: Couldn't read QTOPIA_COMPATIBLE_DEVICES from device specific custom.h \n";
            print "Using default value of Unknown\n";
            $devices = "Unknown";
        }
    } else {
        print "Could not open device specific custom.h to obtain list of compatible devices\n";
        print "Using default value of Unknown\n";
        $devices = "Unknown";
    }
    return $devices;
}

sub run
{
    my @cmd = @_;
    my $cmd = join(" ", @cmd);
    DEBUG and print "mkpkg debug:  $cmd\n";
    system(@cmd) == 0 or croak "Failed to run $cmd";
}

