#!/usr/bin/perl -s
use strict;
use MBGD;
use MBGD::WWW;
use RECOG::DomClustCommon;
use RECOG::FindcoreUtil;

$main::DEBUG = 1;

###############################################################################
#
$main::MIN_NBR_WIN = 10;
$main::MAX_NBR_WIN = 30;
#
$main::MIN_CONS_RATIO = 0.0;
$main::MAX_CONS_RATIO = 1.0;
#
$main::MIN_NBR_CONS_RATIO = 0.0;
$main::MAX_NBR_CONS_RATIO = 1.0;


###############################################################################
#
sub printError {
    my($msg) = shift;

    print "Content-type: text/plain\n";
    print "\n";

    print "#STATUS=", $FindcoreUtil::STA_STRerror, "\n";
    print "#STATUS2=$msg\n";

    return;
}

###############################################################################
#
sub checkArgsForFindcore {
    my($refFormOpt) = shift;
    my($key);

    if (exists($refFormOpt->{'CORE_TAB_ID'})) {
        # [$B<B9TCf$N2r@O$N>uBVLd$$9g$o$;(B]
        # $B$b$7$/$O(B
        # [$B4{B8$N2r@O7k2L$N<hF@(B]
    }
#    elsif (exists($refFormOpt->{'CLUST_TAB_ID'}) && exists($refFormOpt->{'REF_SPEC'})) {
    elsif (exists($refFormOpt->{'CLUST_TAB_ID'})) {
        # [$B?75,2r@OMW5a(B]
        # $B$b$7$/$O(B
        # [$B<B9TCf$N2r@O$N>uBVLd$$9g$o$;(B]$B!J(BCORE_TAB_ID $B$r;XDj$7$J$$%1!<%9!K(B
    }
    else {
        # $B2r@O>r7o$,ITB-(B
#        my($msg) = "Require some analysis options. :: CORE_TAB_ID or (CLUST_TAB_ID + REF_SPEC)";
        my($msg) = "Require some analysis options. :: CORE_TAB_ID or CLUST_TAB_ID";
#        printError($msg);
        my($eid) = $FindcoreUtil::ERRNO_NG_OPTIONS;
        my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
        printErrMsgExit($eid, $emsg);
    }

    #
    $key = 'NBR_WIN';
    if (exists($refFormOpt->{"$key"})) {
        if (($refFormOpt->{"$key"} < $main::MIN_NBR_WIN) || ($main::MAX_NBR_WIN < $refFormOpt->{"$key"})) {
            my($msg) = "Out of range [$main::MIN_NBR_WIN <= $key <= $main::MAX_NBR_WIN]";
#            printError($msg);

            my($eid) = $FindcoreUtil::ERRNO_NG_OPTIONS;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg);
        }
        print STDERR "DBG :: OK ($key)\n" if ($main::DEBUG);
    }

    $key = 'CONS_RATIO';
    if (exists($refFormOpt->{"$key"})) {
        if (($refFormOpt->{"$key"} < $main::MIN_CONS_RATIO) || ($main::MAX_CONS_RATIO < $refFormOpt->{"$key"})) {
            my($msg) = "Out of range [$main::MIN_CONS_RATIO <= $key <= $main::MAX_CONS_RATIO]";
#            printError($msg);
            my($eid) = $FindcoreUtil::ERRNO_NG_OPTIONS;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg);
        }
        print STDERR "DBG :: OK ($key)\n" if ($main::DEBUG);
    }

    $key = 'NBR_CONS_RATIO';
    if (exists($refFormOpt->{"$key"})) {
        if (($refFormOpt->{"$key"} < $main::MIN_NBR_CONS_RATIO) || ($main::MAX_NBR_CONS_RATIO < $refFormOpt->{"$key"})) {
            my($msg) = "Out of range [$main::MIN_NBR_CONS_RATIO <= $key <= $main::MAX_NBR_CONS_RATIO]";
#            printError($msg);
            my($eid) = $FindcoreUtil::ERRNO_NG_OPTIONS;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg);
        }
        print STDERR "DBG :: OK ($key)\n" if ($main::DEBUG);
    }

    return;
}

###############################################################################
#
sub printResult {
    my($refSta) = shift;
    my($coreTabId) = $refSta->{'core_tab_id'};

    my($refOpt) = FindcoreUtil::parseCoreCmdOpts($refSta->{'cmd'});
    my($species) = $refOpt->{'SPECIES'};

    print "Content-type: text/plain\n";
    print "\n";

    print "#STATUS=finished\n";
    print "#SPECIES=$species\n";

    FindcoreUtil::printFindcoreResult($coreTabId);

    return;
}

###############################################################################
#
sub findcore {
    my($refFormOpt) = @_;

    #
    my($dbname) = $main::DBNAME_RECOG;
    my($dbRecog) = MBGD::DB->new($dbname);

    #
    FindcoreUtil::createCoreIndexTable($dbRecog);

    #
    my($coreTabId);
    my($refSta);
    if (exists($refFormOpt->{'CORE_TAB_ID'})) {
        $coreTabId = $refFormOpt->{'CORE_TAB_ID'};
        $refSta = FindcoreUtil::getCoreStatus($dbRecog, $coreTabId);
        if (!$refSta) {
            # $B2r@O7k2L$,B8:_$7$J$$(B
            my($msg) = "Unknown CORE_TAB_ID :: [$refFormOpt->{'CORE_TAB_ID'}]";
#            printError($msg);
            my($eid) = $FindcoreUtil::ERRNO_NO_CLUST_TAB;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg, $refFormOpt->{'CORE_TAB_ID'});
        }
    }
    else {
        # $B2r@O>r7o$+$i(B coreTabId $B$r:n@.(B
        my($clustTabId) = $refFormOpt->{'CLUST_TAB_ID'};
        my($refTabSpec) = FindcoreUtil::getSpeciesByClusterTabId($dbRecog, $clustTabId);
        if (!defined($refTabSpec)) {
            my($msg) = "Can not found Cluster-Table-Id [$clustTabId]";
#            printError($msg);
            my($eid) = $FindcoreUtil::ERRNO_NO_CLUST_TAB;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg, $clustTabId);
        }
        my($refSpOrder) = [ split(/,/, $refTabSpec->{'SPECIES'}) ];

        #
        my($refOpt) = {};
        $refOpt->{'-CLUST_TAB_ID'}   = $clustTabId;
        $refOpt->{'-SPECIES'}        = $refTabSpec->{'SPECIES'};
        $refOpt->{'-refsp'}          = $refFormOpt->{'REF_SPEC'};
        $refOpt->{'-NBR_WIN'}        = $refFormOpt->{'NBR_WIN'};
        $refOpt->{'-CONS_RATIO'}     = $refFormOpt->{'CONS_RATIO'};
        $refOpt->{'-NBR_CONS_RATIO'} = $refFormOpt->{'NBR_CONS_RATIO'};
        $refOpt->{'-OutGroup'}       = $refTabSpec->{'OUT_GROUP'};
        $refOpt->{'-out_species'}    = $refTabSpec->{'SPECIES'};
        $refOpt->{'-SpGrp'}          = $refFormOpt->{'SP_GROUP'};
        $coreTabId = FindcoreUtil::findCoreTabId($dbRecog, $refOpt);

        $refSta = FindcoreUtil::getCoreStatus($dbRecog, $coreTabId);
    }

    #
    if (!$refSta) {
        # $B2r@OL$<B9T(B ==> CoreTabId $B$r:NHV(B + findcore $B$r<B9T(B + $B?JD=I=<((B

        # Core$B9=B$2r@O$NA0=`Hw(B
        my($dirBase) = sprintf("%s/work", $ENV{'MBGD_HOME'});
        my($refOpt) = {};
        $refOpt->{'CLUST_TAB_ID'} = $refFormOpt->{'CORE_TAB_ID'};
        my($refCoreOpt) = FindcoreUtil::setupFindcore($dirBase, $refFormOpt);

        # $B?75,:NHV$5$l$?(B CORE_TAB_ID
        $coreTabId = $refCoreOpt->{'CORE_TAB_ID'};

        # fork() $BA0$K(B MySQL $B$H$N%3%M%/%7%g%s$r@ZCG(B
        $dbRecog->disconnect();

        # findcore $B$r<B9T(B + $B?JD=I=<((B
        my($pid) = fork();
        if ($pid) {
            # $B;R%W%m%;%9$G(B findcore $B$r<B9T(B ==> $B$7$P$i$/(B sleep()
            sleep(1);

            # $B?F%W%m%;%9$K$*$$$F(B MySQL $B$H:F@\B3(B
            my($dbRecog) = MBGD::DB->new($dbname);

            # $B99?7$5$l$?>pJs$r<hF@(B
            $refSta = FindcoreUtil::getCoreStatus($dbRecog, $coreTabId);

            # $B$3$N$"$H$G?JD=I=<((B
        }
        elsif (defined($pid)) {
            close(STDIN);
            close(STDOUT);
            close(STDERR);

            # $B;R%W%m%;%9$K$*$$$F(B MySQL $B$H:F@\B3(B
            my($dbRecog) = MBGD::DB->new($dbname);

            # findcore $B$N<B9T!J(BMySQL $B$N%9%F!<%?%9$r(B '$B<B9TCf(B' $B$KJQ99!K(B
            FindcoreUtil::execFindcore($dbRecog, $refCoreOpt);

            #
            my($fileCoreResult)   = sprintf("%s/core_result", $refCoreOpt->{'DIR_WORK'});
            FindcoreUtil::writeFindcoreResult($refCoreOpt->{'alignout'},
                                              $refCoreOpt->{'core_clustout'},
                                              $fileCoreResult);

            # findcore $B$N2r@O7k2L$r(B MySQL $B$KEPO?(B
            my($fileCore)  = sprintf("%s/", $refCoreOpt->{'DIR_WORK'});
            FindcoreUtil::insertCoreFile($dbRecog,
                                         $refCoreOpt->{'CORE_TAB_ID'},
                                         $fileCoreResult);

            # MySQL $B$N%9%F!<%?%9$r(B '$B2r@O=*N;(B' $B$KJQ99(B
            FindcoreUtil::updateCoreStatus($dbRecog,
                                           $refCoreOpt->{'CORE_TAB_ID'},
                                           $FindcoreUtil::STA_finished);

            # $B:n6H%G%#%l%/%H%j$N:o=|(B
            File::Path::rmtree("$refCoreOpt->{'DIR_WORK'}");

            exit(0);
        }
        else {
            # fork() $B$G%(%i!<(B
            my($msg) = "System Internal Error :: Can not fork() :: $!";
#            printError($msg);
            my($eid) = $FindcoreUtil::ERRNO_FORK;
            my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
            printErrMsgExit($eid, $emsg, $coreTabId);
        }
    }
    elsif ($refSta->{'status'} == $FindcoreUtil::STA_finished) {
        # findcore $B2r@O$,@5>o=*N;$7$F$$$k(B ===> $B2r@O7k2L$r=PNO(B
        print "Content-type: text/plain\n";
        print "\n";
        FindcoreUtil::printFindcoreResultHeader($refSta);
        FindcoreUtil::printFindcoreResult($dbRecog, $coreTabId);
        exit(0);
    }
    if ($refSta->{'status'} == $FindcoreUtil::STA_error) {
        # findcore $B2r@O$,0[>o=*N;$7$F$$$k(B ==> $B%(%i!<%a%C%;!<%8$r=PNO(B
        my($msg) = "System Internal Error :: $refSta->{'core_tab_id'} :: findcore status = $refSta->{'status'}";
#        printError($msg);
        my($eid) = $FindcoreUtil::ERRNO_SERVER_INTERNAL;
        my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
        printErrMsgExit($eid, $emsg, $refSta->{'core_tab_id'});
    }
    elsif ($FindcoreUtil::STA_waiting <= $refSta->{'status'}) {
        # findcore $B$r<B9TCf(B ==> $B$3$N$"$H$G?JD=I=<((B
    }
    else {
        # status $B$,0[>oCM(B ==> $B%(%i!<%a%C%;!<%8$r=PNO(B
        my($msg) = "System Internal Error :: $refSta->{'core_tab_id'} :: findcore status = $refSta->{'status'}";
#        printError($msg);
        my($eid) = $FindcoreUtil::ERRNO_SERVER_INTERNAL;
        my($emsg) = $FindcoreUtil::ERRMSG{"$eid"};
        printErrMsgExit($eid, $emsg, $refSta->{'core_tab_id'});
    }

    # $B?JD=I=<((B
    print "Content-type: text/plain\n";
    print "\n";
    FindcoreUtil::printFindcoreResultHeader($refSta);

    return;
}

###############################################################################
if ($0 eq __FILE__) {
    my($www) = MBGD::WWW->new();
    my($cgi) = $www->cgi();

    my(%args)  = $www->cgiGetArgs();

    if ($main::TAB_ID) {
        $args{'SRC_CLUST_TAB_ID'} = $main::TAB_ID;
    }
    if ($main::MODE) {
        $args{'mode_cluster'} = $main::MODE;
    }

    #
    my(@keyList) = ('CORE_TAB_ID',
                    'CLUST_TAB_ID',
                    'REF_SPEC',
                    'NBR_WIN',
                    'CONS_RATIO',
                    'NBR_CONS_RATIO',
                    'SP_GROUP',
                    );
    my($refFormOpt) = {};
    foreach my$key (@keyList) {
        next if (!exists($args{"$key"}));
        next if ($args{"$key"} =~ /^\s*$/);

        my($v) = $args{"$key"};
        $v =~ s#[^A-Z0-9_\.\-\:\,]##gi;
        $refFormOpt->{"$key"} = $v;
        print STDERR "DBG :: set $key << $v\n" if ($main::DEBUG);
    }


    # $B2r@O>r7o$,$=$m$C$F$$$k$+!)!J$=$m$C$F$$$J$$>l9g(B exit $B$9$k!K(B
    checkArgsForFindcore($refFormOpt);

    #
    findcore($refFormOpt);
}

1;
