#!/usr/bin/env perl
use LWP::Simple;
use JSON;
use warnings;

sub get_github_auth {
    open FH , "<" , $ENV{HOME} . "/.gitconfig";
    local $/;
    my $content = <FH>;
    close FH;
    my @parts = split /(?=\[.*?\])/,$content;
    for my $part ( @parts ) {
        if( $part =~ /^\[github\]/ ) {
            my ($user) = ($part =~ m/user\s*=\s*(\w+)/ );
            my ($token) = ($part =~ m/token\s*=\s*(\w+)/ );
            return {
                user => $user,
                token => $token
            };
        }
    }
}

my $act = shift;

$SIG{INT} = sub {
    exit;
};

if( ! $act || $act eq 'help' ) 
{

    print <<'END';

App::gh

show help message;

    $ gh help

list all repository of c9s:

    $ gh list c9s

clone Plack repository from miyagawa:

    $ gh clone miyagawa/Plack   # default: read-only 

or:

    $ gh clone miyagawa Plack

    $ gh clone gugod Social http

    $ gh clone clkao Web-Hippie ro

clone from read-only uri:

    $ gh clone miyagawa/Plack ro 

clone from ssh uri:

    $ gh clone miyagawa/Plack ssh  

search repository:

    $ gh search Plack

to clone all repository of miyagawa:

    $ gh cloneall miyagawa 

    $ gh cloneall clkao ro  # read-only

to fork project

    $ gh fork clkao AnyMQ

END
    exit;

}
elsif( $act eq 'search' || $act eq 's' ) {
    my $keyword = shift;
    my $json = get 'http://github.com/api/v2/json/repos/search/' . $keyword;

    my $result = decode_json( $json );
    my $width = 78;
    my $column_w = 0;

    my @ary = ();
    for my $repo ( @{ $result->{repositories} } ) {
        my $name = sprintf "%s/%s", $repo->{username} , $repo->{name};
        my $desc = $repo->{description};
        $column_w = length($name) if length($name) > $column_w ;
        push @ary, { name => $name , desc => $desc };
    }

    for my $arg ( @ary ) {
        print $arg->{name};
        my $padding = $column_w - length( $arg->{name} );
        print " " x $padding;
        print " - ";
        print $arg->{desc};
        print "\n";

    }
}
elsif( $act eq 'clone' || $act eq 'c' ) {
    my $user;
    my $repo;

    $user = shift;
    if( $user =~ /\// ) {
        ($user,$repo) = split /\//,$user;
    }
    else {
        $repo = shift;
    }

    my $attr = shift || 'ro';
    my $uri;
    if( $attr eq 'ro' ) {
        $uri = sprintf "git://github.com/%s/%s.git" , $user , $repo;
    }
    elsif( $attr eq 'ssh' ) {
        $uri = sprintf "git\@github.com:%s/%s.git" , $user , $repo;
    }
    print $uri . "\n";
    system( qq{git clone $uri} );
}
elsif( $act eq 'list' ) 
{
    my $acc = shift;
    my $json = get 'http://github.com/api/v2/json/repos/show/' . $acc;
    my $data = decode_json( $json );
    for my $repo ( @{ $data->{repositories} } ) {
        my $repo_name = $repo->{name};
        print $acc . "/" . $repo->{name}  . ' - ' . ($repo->{description}||"") . "\n";
    }
}
elsif( $act eq 'cloneall' || $act eq 'ca' ) {
    my $acc = shift;
    my $attr = shift || 'ro';

    my $json = get 'http://github.com/api/v2/json/repos/show/' . $acc;
    my $data = decode_json( $json );

    for my $repo ( @{ $data->{repositories} } ) {
        my $repo_name = $repo->{name};
        my $local_repo_name = $repo_name;
        $local_repo_name =~ s/\.git$//;

        my $uri;
        if( $attr eq 'ro' ) {
            $uri = sprintf "git://github.com/%s/%s.git" , $acc , $repo_name;
        }
        elsif( $attr eq 'ssh' ) {
            $uri = sprintf "git\@github.com:%s/%s.git" , $acc , $repo_name;
        }
        print $uri . "\n";

        if( -e $local_repo_name ) {
            print "Updating " . $local_repo_name . " ...\n";
            qx{ cd $local_repo_name ; git pull origin master };
        }
        else {
            print "Cloning " . $repo->{name} . " ...\n";
            qx{ git clone -q $uri };
        }
    }
}
elsif( $act eq 'fork' ) {
    my $user;
    my $repo;

    $user = shift;
    if( $user =~ /\// ) {
        ($user,$repo) = split /\//,$user;
    }
    else {
        $repo = shift;
    }

    my $auth = get_github_auth();

    # curl -F 'login=schacon' -F 'token=XXX' http://github.com/api/v2/yaml/repos/fork/dim/retrospectiva

=pod

$VAR1 = {
          'repository' => {
                            'has_downloads' => bless( do{\(my $o = 1)}, 'JSON::XS::Boolean' ),
                            'owner' => 'c9s',
                            'has_issues' => bless( do{\(my $o = 0)}, 'JSON::XS::Boolean' ),
                            'name' => 'AnyMQ',
                            'private' => $VAR1->{'repository'}{'has_issues'},
                            'has_wiki' => $VAR1->{'repository'}{'has_downloads'},
                            'pushed_at' => '2010/04/06 00:40:45 -0700',
                            'description' => 'Simple message queue based on AnyEvent',
                            'watchers' => 1,
                            'forks' => 0,
                            'homepage' => '',
                            'created_at' => '2010/07/21 06:08:11 -0700',
                            'fork' => $VAR1->{'repository'}{'has_downloads'},
                            'url' => 'http://github.com/c9s/AnyMQ',
                            'open_issues' => 0
                          }
        };
=cut

    my $uri = sprintf("http://github.com/api/v2/json/repos/fork/%s/%s?login=%s&token=%s", $user , $repo , $auth->{user} , $auth->{token} );
    my $json = get( $uri );
    my $data = decode_json( $json );
    # use Data::Dumper; warn Dumper( $data );

    $data = $data->{repository};
    print "Name:       " . $data->{name} . "\n";
    print "Owner:      " . $data->{owner} . "\n";
    print "Watchers:   " . $data->{watchers} . "\n";
    print "Created at: " . $data->{created_at} . "\n";
    print "Pushed at:  " . $data->{pushed_at} . "\n";
    print "Fork:       " . $data->{'fork'} . "\n";
    print "URL:        " . $data->{url} . "\n";
    print "Homepage:   " . $data->{homepage} . "\n";
}
