#!/usr/bin/perl -s
use lib "$ENV{'MBGD_HOME'}/build";
use DirHandle;
use FileHandle;
use POSIX "sys_wait_h";
use MBGD::FuncCat;
use MBGD::FunctionCategory;

require 'libMBGDMotif.pl';
require 'libMBGDDBM.pl';
require "MBGD_Conf.pl";
require "MBGD_commonPath.pl";
#require 'libMBGDFuncCat.pl';

$curr_dir = `dirname $0`; chop $curr_dir;
$Hclnum = 2 if (! defined $Hclnum);

#
$colorDefault = $MBGD::FuncCat::UNKNOWN;

$DIR_database = "$ENV{'MBGD_HOME'}/database.work";
if ($main::DIR) {
    $DIR_database = $main::DIR;
}

#
my($dir_addinfo) = "$ENV{'MBGD_HOME'}/WWW/bin/addinfo.d";
@dbFuncList = get_dbtype_list($dir_addinfo);

if ($descriptorg) {
	$descriptfile = "$DIR_database/sptit/sptit.$descriptorg";
	open(DES, $descriptfile) || die "Open Error($descriptfile)";
	while (<DES>) {
		chop;
		($name, $genename, @tit) = split;
		$genename{$name} = $genename;
		$description{$name} = join(' ', @tit);
	}
	close(DES);
}
if ($classorg) {
	$classfile = "$DIR_database/class/$classorg.class";
	if (open(CLS, $classfile)) {
		while (<CLS>) {
			chop;
			($cl, $id) = split(/\t/);
			$class{"$classorg:$id"} = $cl;
			$maxclass = $cl if ($cl > $maxclass);
		}
		close(CLS);
	}
}

if ($pdb) {
	open(SEL, "$CMD_select -PDB $pdb |") || die "Can not open (select0)";
	while (<SEL>) {
		($entname, $pdbname) = split;
		$pdbname{$entname} .= "," if ($pdbname{$entname});
		$pdbname{$entname} .= "$pdbname";
	}
	close(SEL);
}

#
my($file_addinfo_in) = "$ENV{'MBGD_HOME'}/work/addinfo.in.$$";
my($fh_addinfo_in) = FileHandle->new(">$file_addinfo_in") || die("Can not open $file_addinfo_in($!)");
while (<>) {
    $fh_addinfo_in->print($_);
}
$fh_addinfo_in->close();

#
my($funccat_ref) = {};
my($max_proc) = 5;
my(%pid_hash);
my($PID) = $$;
foreach my$dbtype (@dbFuncList) {
    for (;;) {
        my(@pid_list) = keys(%pid_hash);
        foreach my$pid (@pid_list) {
            my($ret) = waitpid($pid, POSIX::WNOHANG);
            if ($ret == $pid) {
                delete($pid_hash{"$pid"});
            }
        }

        my(@pid_list) = keys(%pid_hash);
        if (scalar(@pid_list) <= $max_proc) {
            last;
        }
        sleep(5);
    }

    my($pid) = fork();
    if ($pid) {
        $pid_hash{"$pid"} = 1;
    }
    elsif (defined($pid)) {
        my($file_addinfo_out) = "$ENV{'MBGD_HOME'}/work/addinfo.out.$dbtype.$PID";
        my($opt) = "-SUBCLUST='$main::SUBCLUST'";
        my($cmd) = "$dir_addinfo/$dbtype $opt $file_addinfo_in > $file_addinfo_out";
        print STDERR "CMD :: $cmd $file_addinfo_in\n";
        system("$cmd");
        exit(0);
    }
    else {
        die("Can not fork!");
    }
}

#
my(@pid_list) = keys(%pid_hash);
foreach my$pid (@pid_list) {
    print STDERR "Waiting pid=$pid\n";
    waitpid($pid, 0);
}
print STDERR "Done.\n";

unlink($main::FILE_category) if ($main::FILE_category);
foreach my$dbtype (@dbFuncList) {
    my($file_addinfo_out) = "$ENV{'MBGD_HOME'}/work/addinfo.out.$dbtype.$PID";
    my($cmd) = "$main::CMD_cat $file_addinfo_out";
    $cmd .= " >> $main::FILE_category" if ($main::FILE_category);
    system("$cmd");
    unlink($file_addinfo_out);
}

exit(0);

#
foreach my$dbtype (@dbFuncList) {
    my($file_addinfo_out) = "$ENV{'MBGD_HOME'}/work/addinfo.out.$dbtype.$PID";
    my($fh_funccat) = FileHandle->new("$file_addinfo_out") || die("Can not open $file_addinfo_out($!)");

    $funccat_ref->{"$dbtype"} = {};
    while (my$line=$fh_funccat->getline()) {
        next if ($line =~ /^\s*#/);
        next if ($line =~ /^\s*$/);

        $line =~ s#[\r\n]*$##;
        my($clustid, $level, $weight) = split(/\t/, $line);
        if (!exists($funccat_ref->{"$dbtype"}->{"$clustid"})) {
            $funccat_ref->{"$dbtype"}->{"$clustid"} = [];
        }
        my($ent) = { 'LEVEL' => $level,
                     'WEIGHT' => $weight,
                    };
        push(@{$funccat_ref->{"$dbtype"}->{"$clustid"}}, $ent);
    }
    $fh_funccat->close();
    print STDERR "CMD :: $cmd $file_addinfo_in :: Done.\n";
}

#
my($fhCategory);
if ($main::FILE_category) {
    $fhCategory = FileHandle->new(">$main::FILE_category") || die("Can not open $main::FILE_category($!)");
}
else {
    $fhCategory = FileHandle->new(">/dev/null");
}

#
my($fh_addinfo_in) = FileHandle->new("$file_addinfo_in") || die("Can not open $file_addinfo_in($!)");
while ($_=$fh_addinfo_in->getline()) {
	if (/^#/) {
		if (/SPEC/) {
			($specstr) = /-SPEC=(\S+)/;
			@species = split(/,/, $specstr);
            print STDERR "LOG :: SPEC :: @species\n";
		}
		print;
		next;
	}
	s#[\r\n]*$##;

	my@data = split(/\t/, $_, -1);
    my($cluster_id) = $data[0];
    my($homcluster_id) = $data[1];
    my($num_spec) = $data[2];
	if (defined @speceis) {
		@names = @data[$Hclnum+1..$Hclnum+1+$#species];
	} else {
		@names = @data[$Hclnum+1..$#data];
	}

	$buf = $_;

	if ($pdb) {
		undef %found_pdbname;
		foreach $nms (@names) {
			foreach $nm (split(/ /, $nms)) {
				foreach $pn (split(/,/, $pdbname{$nm})) {
					$found_pdbname{$pn} = 1;
				}
			}
		}

		$buf .= "\t";

		$flag = 0;
		foreach $n (keys %found_pdbname) {
			$buf .= " " if ($flag);
			$buf .= "$n";
			$flag = 1;
		}
	}
	if ($classorg) {
		($ent) = split(/ /, $names[$classcol]);
		if ($ent =~ /sp:(.*)$/) {
			$entname = $1;
			($dmy,$sp) = split(/_/, $entname);
##			print "\t $sp:$entname*", $class{"$sp:$entname"};
			if (! $class{"$sp:$entname"}) {
				$buf .= "\t" . $maxclass;
			} else {
				$buf .= "\t" . $class{"$sp:$entname"};
			}
		} else  {
###			$class{$ent} = $maxclass if (! $class{$ent});
			if ($class{$ent}) {
				$buf .= "\t$class{$ent}";
			} else {
				$buf .= "\t$maxclass";
			}
		}
	}
	if ($descriptorg) {
		($ent) = split(/ /, $names[$descriptcol]);
		$buf .= "\t$description{$ent}";
	}

##########
	print $buf;

	#
	if ($cons_gene) {
		my($cntColor_ref) = {};
        my($nm,$ent,$sp,$orf,$funccat,$col,%CntGene);

		foreach my$nm (@names) {
			foreach my$ent (split(/ /, $nm)) {
				my($sp, $orf) = split(/:/, $ent);
				$ent =~ s/\(\d+\)//; # $B%I%a%$%s>pJs$r:o=|(B
				if ($cons_gene) {
					my $gene = &get_genename_mysql($ent);
					$CntGene{$gene}++ if ($gene);
				}

if (0) {
				if ($category_col) {
					#
                    foreach $dbFunc (@dbFuncList) {
                        $refFuncCategory = $refFuncCat{"$dbFunc"};
                    	$colorDefault = $colorDefault{"$dbFunc"};

    					my($refFuncList) = $refFuncCategory->getFunctionListBySporf($ent);
                        my($nFuncList)   = $refFuncCategory->countFunctionListBySporf($ent);
		    			foreach my$refFunc (@{$refFuncList}) {
			    			$colid = $refFunc->{'LEVEL'};
				    		if ($colid && $colid != $colorDefault) {
					    		# $B$R$H$D$N(B Gene $B$KJ#?t$N5!G=$,3d$jEv$F$i$l$F$$$k>l9g!"=E$_$E$1$rEyJ,$9$k(B
						    	$cntColor_ref->{"$dbFunc"}->{$colid} += 1 / $nFuncList;
#print STDERR "DBG :: $ent :: $colid :: ", 1 / $nFuncList, "\n";
    						}
	    				}
                    }
				}
}
			}
		}

		# $BBeI=(B Gene $B$N7hDj(B
		if ($cons_gene) {
			my($c, $max, $maxc);
			foreach $c (sort {$a cmp $b} keys %CntGene) {
				if ($max < $CntGene{$c}) {
					$max = $CntGene{$c};
					$maxc = $c;
				}
			}
			print "\t$maxc";
		}

        # $BBeI=5!G=%+%F%4%j?'$N7hDj(B
		if ($category_col) {
            foreach $dbtype (@dbFuncList) {
                my($is_best) = 1;
                foreach my$ent (@{$funccat_ref->{"$dbtype"}->{"$clustid"}}) {
                    $fhCategory->print(join("\t", $cluster_id,
                                                  $dbtype,
                                                  $ent->{'LEVEL'},
                                                  $ent->{'WEIGHT'},
                                                  $is_best) . "\n");
                    $is_best = 0;
                }
            }
		}
	}
	print "\n";
}
$fh_addinfo_in->close();
$fhCategory->close();

unlink("$file_addinfo_in");

exit(0);

###############################################################################
sub get_dbtype_list {
    my($dir) = shift;

    #
    my(@dbtype_list);

    #
    if (!$dir) {
        $dir ="$ENV{'MBGD_HOME'}/WWW/bin/addinfo.d";
    }
    if (! -d $dir) {
        return @dbtype_list;
    }

    #
    my($dh) = DirHandle->new("$dir") || die("Can not open $dir($!)");
    while (my$file=$dh->read()) {
        next if ($file =~ /^\./);
        next if ($file =~ /\.bak$/i);
        next if ($file =~ /\.sample$/i);
        next if (! -f "$dir/$file");
        next if (! -x "$dir/$file");

        push(@dbtype_list, $file);
    }

    return @dbtype_list;
}

###############################################################################
1;#
###############################################################################
__END__

# data file format :: addinfo_in

##  # ..... SPEC=sp1,sp2,.....,spN .....
##  cluster_id \t homcluster_id \t num_spec \t spname1_1 spname1_2 \t spname2_1 \t ... \t spnameN_1 spanmeN_N

