#!/usr/bin/env perl

use strict;
use warnings FATAL => 'uninitialized';
use utf8;

use Cwd 'abs_path';

my ($mydir, $myname);

BEGIN {
    my $location = (-l $0) ? abs_path($0) : $0;
    $location =~ /(.*?)([^\/]+)\z/s or die "?";
    ($mydir, $myname) = ($1, $2);
}

use lib "$mydir/../lib";

use Chj::xtmpfile;
use Chj::xopen 'xopen_read';

(my $email = 'ch%christianjaeger,ch') =~ tr/%,/@./;

sub usage {
    print STDERR map {"$_\n"} @_ if @_;
    print "$myname ..

  (Christian Jaeger <$email>)
";
    exit(@_ ? 1 : 0);
}

use Getopt::Long;
our $verbose = 0;
our $opt_opspaces;
our $opt_functionparameters2signatures;

#our $opt_dry;
GetOptions(
    "verbose"                       => \$verbose,
    "help"                          => sub {usage},
    "opspaces"                      => \$opt_opspaces,
    "functionparameters2signatures" => \$opt_functionparameters2signatures,

    #"dry-run"=> \$opt_dry,
) or exit 1;

sub opspaces {
    if (/http|href/) {
        $_
    } else {
        s{ ([^/>=~<!|+*-]) (=|=>|==|=~|/=|//=|>=|<=|<<|>>|!=|\|\||\|\|=|\+=|-=|\*=) ([^/>=~<!|]) }{
            my ($a,$b,$c)=($1,$2,$3);
            my $all = "$a$b$c";
            my $pre= substr($_, 0, pos($_)+1);
            my $is_perl = 0;
            if ($b eq "=>") {
                $is_perl = 1
            } elsif (not substr($pre, length($pre)-1, 1)=~ /\w/) {
                $is_perl = 1
            } elsif (my ($sigil) = $pre =~ /([^\w])[A-Za-z_]\w*\s*$/) {
                $is_perl= $sigil =~ /[\$*&@%]/
            }
            #use FP::Repl;repl;
            if ($is_perl) {
                ($a eq " " ? $a : "$a ").$b.($c eq " " ? $c : " $c")
            } else {
                $all
            }
        }sgex and s/[ \t]*$//;
        $_
    }
}

sub functionparameters2signatures {
    s{
         \b(method|fun)(\s+\w+)
         (?:
             (\s*\(\s*)
             ([^()]*?)
             (\s*\))
         )?
         (\s*\{)
    }{
         my ($which,$name,$a,$b,$c,$end)=($1,$2,$3,$4,$5,$6);
         "sub$name"
           . ($which eq "method" ? 
              (defined($b) ? $a.(length($b) ? q{$self, }.$b : q{$self}).$c
               : q{($self)})
              : "$a$b$c")
           . $end
    }sgex;
    $_
}

for my $file (@ARGV) {
    my $f     = xopen_read $file;
    my @lines = do {
        local $/ = $opt_functionparameters2signatures ? undef : $/;
        die "can't satisfy both options at same time here^ "
            if $opt_functionparameters2signatures && $opt_opspaces;
        $f->xreadline;
    };
    $f->xclose;

    my $t = xtmpfile $file;
    $t->xprint(
        map {
            $_ = opspaces $_ if $opt_opspaces;
            $_ = functionparameters2signatures $_
                if $opt_functionparameters2signatures;
            $_
        } @lines
    );
    $t->xclose;
    $t->xputback;
}

