#!/usr/bin/perl
# SourceForge.JP Wiki manipulator
# by hylom
# This code is under GPL.
#

use warnings;
use strict;

use lib 'C:\Users\hirom\bin/otptools';

use utf8;
use open IO => ':utf8';
use open ':std';

use Getopt::Std;
use SourceForgeJP;
use IO::File;
use Term::Prompt;
use URI::Escape;
use Encode;
use File::Temp;

my $usage = <<EOD;
sfwman.pl command [options]

example:
    sfwman.pl login -u loginname -p password
    sfwman.pl logout
    sfwman.pl get -p projectname -t targetpage
    sfwman.pl edit -p projectname -t targetpage -f textfile -c comment
    sfwman.pl delete -p projectname -t targetpage
    sfwman.pl rdelete -p projectname -e expr
    sfwman.pl attach -p projectname -t targetpage -f attachmentfile
    sfwman.pl list -p projectname
    sfwman.pl filter -p projectname -t targetpage -c filtercommand
    sfwman.pl rfilter -p projectname -e expr -c filtercommand

EOD

    my $command = shift @ARGV;
unless( $command ) {
    print $usage;
    exit;
}

if( $command eq 'login' ) {   #login
    my %opts;
    getopt('up', \%opts);
    my $login_name;
    my $password;

    if( defined $opts{'u'} ) {
	$login_name = $opts{'u'};
    } else {
	$login_name = prompt( 'x', 'loginname:', '', '' );
    }

    if( defined $opts{'p'} ) {
	$password = $opts{'p'};
    } else {
	$password = prompt( 'p', 'password:', '', '' );
	print "\n";
    }

    print "do login...\n";
    if( login( $login_name, $password) ) {
		print "ok.\n";
	} else {
		print "login failed.\n"
	}

} elsif( $command eq 'attach' ) {    #attach
    my %opts;
    getopt('ptf', \%opts);

    my $project = $opts{'p'};
    my $page = $opts{'t'};
    my $file = $opts{'f'};

    add_attachment( $project, $page, $file );
    
} elsif( $command eq 'get' ) {    #get
    my %opts;
    getopt('pt', \%opts);
    my $project = $opts{'p'};
    my $page = $opts{'t'};

    getrawtext( $project, $page);

} elsif( $command eq 'list' ) {    #list
    my %opts;
    getopt('p', \%opts);
    my $project = $opts{'p'};

    get_page_list( $project);

} elsif( $command eq 'delete' ) {    #delete
    my %opts;
    getopt('pt', \%opts);
    my $project = $opts{'p'};
    my $page = $opts{'t'};

    delete_page( $project, $page);

} elsif( $command eq 'rdelete' ) {    #regdelete
    my %opts;
    getopt('pe', \%opts);
    my $project = $opts{'p'};
    my $expr = $opts{'e'};

    regdelete( $project, $expr);

} elsif( $command eq 'filter' ) {    #filter
    my %opts;
    getopt('ptfc', \%opts);
    my $project = $opts{'p'};
    my $page = $opts{'t'};
    my $command = $opts{'f'};
    my $comment = $opts{'c'};

    filter( $project, $page, $command, $comment);

} elsif( $command eq 'rfilter' ) {    #rfilter
    my %opts;
    getopt('pefc', \%opts);
    my $project = $opts{'p'};
    my $expr = $opts{'e'};
    my $command = $opts{'f'};
    my $comment = $opts{'c'};

    regfilter( $project, $expr, $command, $comment);

} elsif( $command eq 'edit' ) {    #edit
    my %opts;
    getopt('ptfc', \%opts);

    my $project = $opts{'p'};
    my $page = $opts{'t'};
    my $file = $opts{'f'};
    my $comment = $opts{'c'};

    edit( $project, $page, $file, $comment);

} elsif( $command eq 'logout' ) {    #logout
    print "do logout...\n";
    logout();

} else {    #other
    print $usage;
    exit;
}

sub login {
    my $login_name = shift @_;
    my $password = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    $sf->login( $login_name, $password );
}

sub logout {
    my $sf = WWW::SourceForgeJP->new();
    $sf->logout();
}

sub getrawtext {
    my $project = shift @_;
    my $page = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    print $sf->Wiki->get_raw_text( $project, $page );
}

sub delete_page {
    my $project = shift @_;
    my $page = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    if( $sf->Wiki->delete_page( $project, $page ) ) {
	print "delete $page: succeed.\n";
    } else {
	print "delete $page: failed.\n";
    }

}

sub get_page_list {
    my $project = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    my $page_list_ref = $sf->Wiki->get_page_list( $project );

    for my $page (@{$page_list_ref}) {
	my $page_str = uri_unescape( $page );

	print $page_str, "\n";
    }
}

sub edit {
    my $project = shift @_;
    my $page = shift @_;
    my $file = shift @_;
    my $comment = shift @_;

    $comment = "" if( ! defined $comment );

    my $file_handle = IO::File->new($file, "r") or die "$! : $file\n" ;
    my $text = do { local $/; <$file_handle> };

    my $sf = WWW::SourceForgeJP->new();

    $sf->Wiki->edit_page( project => $project,
			  page => $page,
			  text => $text,
			  comment => $comment );
}

sub add_attachment {
    my $project = shift @_;
    my $page = shift @_;
    my $file = shift @_;

    if( ! -e $file ) {
	die "$file is not exist.\n";
    }

    my $sf = WWW::SourceForgeJP->new();

    my $ret = $sf->Wiki->post_attachment( project => $project,
					  page => $page,
					  file => $file );

    if( $ret ) {
	print "$file: upload succeed.\n";
    } else {
	print "$file: upload failed.\n";
    }
}

sub regdelete {
    my $project = shift @_;
    my $expr = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    my $page_list_ref = $sf->Wiki->get_page_list( $project );

    for my $page (@{$page_list_ref}) {
	my $page_str = uri_unescape( $page );
	if( $page_str =~ m/$expr/ ) {
	    if( $sf->Wiki->delete_page( $project, $page ) ) {
		print "$page_str : deleted.\n";
	    } else {
		print "$page_str: failed.\n";
	    }
	}
    }
}

sub filter {
    my $project = shift @_;
    my $page = shift @_;
    my $command = shift @_;
    my $comment = shift @_;

    my $sf = WWW::SourceForgeJP->new();
    my $text = $sf->Wiki->get_raw_text( $project, $page );

    my $temp_fh = File::Temp->new();
    binmode $temp_fh, ":utf8";
    my $filename = $temp_fh->filename;
    print $temp_fh $text;

    my $filterd_text = `type $filename | $command`;

    $filterd_text = Encode::decode_utf8( $filterd_text );
#    print $filterd_text;

    my $ret = 1;

    $text = Encode::encode_utf8( $filterd_text );

    $ret = $sf->Wiki->edit_page( project => $project,
				 page => $page,
				 text => $text,
				 comment => $comment );

    if( $ret ) {
	print "$page: done.\n";
    } else {
	print "$page: failed.\n";
    }

}

sub regfilter {
    my $project = shift @_;
    my $expr = shift @_;
    my $command = shift @_;
    my $comment = shift @_;

    print "$project,  $command, $comment, \n";
    die "expr is inbalid.\n" if( ! $expr );

    my $sf = WWW::SourceForgeJP->new();
    my $page_list_ref = $sf->Wiki->get_page_list( $project );

    for my $page (@{$page_list_ref}) {
	my $page_str = uri_unescape( $page );
	if( $page_str =~ m/$expr/ ) {
#	    print $page_str, "\n";
#	    print $project, $page, $command, $comment, "\n";
	    filter( $project, $page, $command, $comment );
	}
    }

}
