#!/usr/bin/env perl6
use Shell::Command;
use Panda;

subset Command of Str where
    'install' | 'list' | 'update' | 'info' | 'search';

sub installprojects($panda, @args) {
    for @args -> $x {
        try {
            $panda.resolve($x);
            CATCH { say $! }
        };
    }
}

sub listprojects($panda) {
    for $panda.ecosystem.project-list -> $p {
        my $x = $panda.ecosystem.get-project($p);
        my $s;
        given $panda.ecosystem.project-get-state($x) {
            when 'installed'     { $s = '[installed]' }
            when 'installed-dep' { $s = '[installed as a dependency]' }
            default              { $s = '' }
        }
        printf "%-20s\t%s\n", $x.name, $s;
    }
}

sub wrap ($str) {
    return $str.comb(/ . ** 0..40 [ << | $ ]/).grep({ .chars > 0 }).join("\n" ~ " " x 36);
}

sub search-projects($panda, $string) {
    for $panda.ecosystem.project-list -> $project {
        my $p = $panda.ecosystem.get-project($project);
        next unless $p.name ~~ / <$string> / || $p.metainfo<description> ~~ / <$string> /;
        printf "%-24s %-10s %s\n",$p.name,$p.version, wrap($p.metainfo<description>);
    }
}

sub projectinfo($panda, @args) {
    for @args -> $p {
        my $x = $panda.ecosystem.get-project($p);
        if $x {
            say $x.name => $x.version;
            say "Depends on:" => $x.dependencies.Str if $x.dependencies;
            given $panda.ecosystem.project-get-state($x) {
                when 'installed'     {
                    say "State:\t\tinstalled";
                }
                when 'installed-dep' {
                    say "State:\t\tinstalled as a dependency";
                }
            }
            for $x.metainfo.kv -> $k, $v {
                if $k ~~ none('version', 'name', 'depends') {
                    say $k.ucfirst => $v;
                }
            }
            say '';
        } else {
            say "Project '$p' not found"
        }
    }
}

sub execute(Command $c, $panda, @args) {
    given $c {
        when 'install' { 
            installprojects($panda, @args);
        }
        when 'list' {
            listprojects($panda);
        }
        when 'update' {
            $panda.ecosystem.update;
        }
        when 'info' {
            projectinfo($panda, @args);
        }
        when 'search' {
            search-projects($panda, @args);
        }
    }
}

# default opts for MAIN
if %*ENV<PANDA_DEFAULT_OPTS> {
    @*ARGS = %*ENV<PANDA_DEFAULT_OPTS> ~ (@*ARGS ?? ' ' ~ @*ARGS !! '');
}

# initialize the Panda object
my $panda;
{
    my $home = $*OS eq 'MSWin32' ?? %*ENV<HOMEDRIVE> ~ %*ENV<HOMEPATH> !! %*ENV<HOME>;
    my $pandadir = "$home/.panda";
    mkpath $pandadir unless $pandadir.IO ~~ :d;

    my $projectsfile = "$pandadir/projects.json";

    $panda = Panda.new(
        srcdir       => "$pandadir/src",
        destdir      => "$home/.perl6",
        statefile    => "$pandadir/state",
        projectsfile => "$pandadir/projects.json"
    );
}

multi MAIN (Command $command, *@args) {
    execute($command, $panda, @args);
}

multi MAIN () {
    while prompt('panda> ') -> $c {
        my ($command, @args) = $c.split(' ');
        if $command ~~ Command {
            try { execute($command, $panda, @args) };
            say $! if $!;
        } else {
            say "Unknown command: $command";
        }
    }
    say ''; # the newline after exiting the REPL
}

sub USAGE {
    say "Usage: panda [command [args]]

Options:
    help
        Display this message and quit
    install [module1 module2]
        Install a modules(s)
    search
        Search module name/description using regex
    list
        List the available packages
    info [module1 module2]
        Display information on a specific module(s)
    update
        Update the module database
";
    exit 0;
}

# vim: ft=perl6
