#!/usr/bin/env perl
use strict;
use lib $ENV{ 'MAIN_CONF'}  ;
use main_config ;
my %commands = () ;

if ( @ARGV <= 0 ) { push ( @{$commands{'help'}}, ' ' ) ; } 
else { (%commands) = main_config::get_commands ( @ARGV ) ; }

my $conf_file ;
if ( -f "main_config.data" )
{    $conf_file = "main_config.data" ; }
else
{    $conf_file = join ('', $ENV{"MAIN_CONF"}, "main_config.data" ) ; }

my %my_main = main_config::read_main_config_file ( $conf_file ) ; 

my $SEGM_DICT ;
if ( -f "segm_names" )
{ $SEGM_DICT = "segm_names" ; }
else
{ $SEGM_DICT = join ('', $ENV{"MAIN_CONF"}, "segm_names" ) ; }

#########################

if ( !exists($my_main{"AUTO_START"}  ) )  { push ( @{$my_main{"AUTO_START"}}, "ON" ) ; }
if ( !exists($my_main{"FILE_MTZ"}  ) )  { push ( @{$my_main{"FILE_MTZ"}}, "" ) ; }
if ( !exists($my_main{"CRYST1_DATA"}  ) )  { push ( @{$my_main{"CRYST1_DATA"}}, "BRAGG" ) ; }
my $fl_group = "FALSE" ; my $fl_cryst = "FALSE" ;
my $fl_strategy = "FALSE" ;
my @all_groups = () ; my @all_crysts = () ; my @all_cryst_data = () ;
my @all_strategy = () ;
my ( $IGR, $WORD, $STRATEGY, $GROUP, $CRYST, $SEGM ) ;

#####################################################################

my $PROC_ERROR = "FALSE" ;
my $doit = "FALSE" ;
my $use_diffraction_file = "FALSE" ;

my $keyword ; 
foreach $keyword ( sort keys (%commands) ) 
{
#print "FOR EACH $keyword --------->> TOTAL NUMBER OF GROUPS", $my_main{"SG_NGROUP"}[0], "\n" ;
    if ( $keyword eq 'h' || substr($keyword, 0,4) eq "help" ) { goto HELP }
    if ( $keyword eq 'a' || substr($keyword, 0,4) eq "auto" ) { goto AUTO }
    if ( $keyword eq 'c' || substr($keyword, 0,7) eq "crystal" ) { goto CRYSTAL }
    if ( $keyword eq 'd' || substr($keyword, 0,4) eq "data" ) { goto DATA }
    if ( $keyword eq 'f' || substr($keyword, 0,4) eq "file" ) { goto FILE }
    if ( $keyword eq 'g' || substr($keyword, 0,5) eq "group" ) { goto GROUP }
    if ( $keyword eq 's' || substr($keyword, 0,8) eq "strategy" ) { goto STRATEGY }
    if ( $keyword eq 'm' || substr($keyword, 0,5) eq "molec" ) { goto MOLEC }
    if ( $keyword eq 'r' || substr($keyword, 0,5) eq "rfree" ) { goto RFREE }
    if ( $keyword eq 'u' || substr($keyword, 0,6) eq "use" ) { goto USE }
    if ( substr($keyword, 0,4) eq "doit" ) { $doit = "TRUE" ; next ; }
    print "unknown option >$keyword<\n" ; $PROC_ERROR = "TRUE" ;

 HELP:
   my $MOLECULES = join ( ' ', @{$my_main{"SG_LIST"}} ) ;
    print << "END_OF_TEXT" ;
  -h|-help|--help) prints this message with available options and current status 
  -m|--molec)      defines the the list of molecular segments 
                   ${$my_main{"SG_NMOL"}}[0] : $MOLECULES
  -c|--crystal )   assigns molecular segments to a crystal form: 
                   specify the lists of segments belonging to crystal forms 
                   for each form embrace the list in " "
END_OF_TEXT
#    print $my_main{"SG_NGROUP"}[0], " XXXXX \n";
for ( $IGR = 1; $IGR <= $my_main{"SG_NCRYST"}[0] ; $IGR++ )
{
#    print "2222 XXXXX\n";
    $CRYST= join ( '', "SG_CRYST" , $IGR ) ;
    $STRATEGY = join ( '', "SG_CRYST" , $IGR, "_STRATEGY" ) ;
#    print $IGR, " CRYST: ", $CRYST, "\n" ;
#    print "{", @{$my_main{$CRYST}}, "} STR: ", $STRATEGY, " ", @{$my_main{$STRATEGY}}, "\n" ;
#    my $LINE = join (" ", $IGR, @{$my_main{$STRATEGY}}, '|', @{$my_main{$CRYST}},  ) ;
if ( exists($my_main{$CRYST}  ) ) 
{
    printf ( "                 %3d | @{$my_main{$CRYST}} \n", $IGR ) ; 
}
}

print << "END_OF_TEXT" ;
  -d|--data)       crystal data kind [BRAGG/DIFFUSE] 
END_OF_TEXT
for ( $IGR = 1; $IGR <= $my_main{"SG_NCRYST"}[0] ; $IGR++ )
{
#    $CRYST= join ( '', "CRYST" , $IGR ) ;
    $STRATEGY = join ( '', "CRYST" , $IGR, "_DATA" ) ;
#    print $IGR, " CRYST: ", $STRATEGY, "\n" ;
#    print "{", @{$my_main{$CRYST}}, "} STR: ", $STRATEGY, " ", @{$my_main{$STRATEGY}}, "\n" ;
#    my $LINE = join (" ", $IGR, @{$my_main{$STRATEGY}}, '|', @{$my_main{$CRYST}},  ) ;
if ( exists($my_main{$CRYST}  ) ) 
{
    printf ( "                 %3d | @{$my_main{$STRATEGY}} \n", $IGR ) ; 
}
}
print << "END_OF_TEXT" ;
  -g|--group)      defines NCS groups: 
                   specify the list of segments belonging to groups 
                   for each group embrace the list in " "
END_OF_TEXT
#    print $my_main{"SG_NGROUP"}[0], " XXXXX \n";
for ( $IGR = 1; $IGR <= $my_main{"SG_NGROUP"}[0] ; $IGR++ )
{
#    print "2222 XXXXX\n";
    $GROUP= join ( '', "SG_GROUP" , $IGR ) ;
    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
#    print $IGR, " GROUP: ", $GROUP, "\n" ;
#    print "{", @{$my_main{$GROUP}}, "} STR: ", $STRATEGY, " ", @{$my_main{$STRATEGY}}, "\n" ;
#    my $LINE = join (" ", $IGR, @{$my_main{$STRATEGY}}, '|', @{$my_main{$GROUP}},  ) ;
if ( exists($my_main{$GROUP}  ) ) 
{
    printf ( "                 %3d %4s  | @{$my_main{$GROUP}} \n", $IGR, @{$my_main{$STRATEGY}} ) ; 
}
}

print << "END_OF_TEXT" ;
  -s|--strategy)   defines scripts strategy [EACH/ONE/LINK/WHOLE/COMPOSIT/BACKGROUND]
                   specify parameters for each group separately [1 EACH] 
                   EACH: average each molecule separately (default)
                   ONE: average one and distribute the averaged density to others
                   LINK: use operators from another group
                   WHOLE: the whole group builds a single mask for proper (spherical) symmetry
                   COMPOSIT: the whole group represents a single structure in multiple conformations
  -u|--use)        extract information from diffraction data file (mtz or sca) [${$my_main{"FILE_MTZ"}}[0]]
  -r|--rfree)      turns ON or OFF use of R-free flag [${$my_main{"DFR_RFREE"}}[0]]
  -a|--auto)       turns ON or OFF generation of auto start file \".main\" [$my_main{"AUTO_START"}[0]]
     --doit)       create all reasonable macros using current definitions
END_OF_TEXT
    exit ;
AUTO:
    $my_main{"AUTO_START"}[0] = uc(shift ( @{$commands{$keyword}} )) ; next ;

GROUP:
$fl_group = "TRUE" ;
@all_groups = () ;
foreach $SEGM ( @{$commands{$keyword}}) { push ( @all_groups, uc($SEGM) ); }
next ;

CRYSTAL:
$fl_cryst = "TRUE" ;
@all_crysts = () ;
foreach $SEGM ( @{$commands{$keyword}}) { push ( @all_crysts, uc($SEGM) ); }
#print " ALL CRYSTALS", @all_crysts "\n" ;
next ;

DATA:
$fl_cryst = "TRUE" ;
@all_cryst_data = () ;
foreach $SEGM ( @{$commands{$keyword}}) { push ( @all_cryst_data, uc($SEGM) ); }
#print " ALL CRYSTALS", @all_cryst_data "\n" ;
next ;

MOLEC:
    $IGR = 0 ; 
@{$my_main{"SG_LIST"}} = () ;
#@all_crysts = () ; 
foreach $SEGM ( @{$commands{$keyword}}) { push ( @{$my_main{"SG_LIST"}}, uc($SEGM) ); }
foreach $SEGM ( @{$my_main{"SG_LIST"}} )
{
    $IGR++ ;
    $GROUP = join ( '', "SG_GROUP" , $IGR ) ;
    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
    @{$my_main{$GROUP}} = () ; $my_main{$GROUP}[0] = $SEGM ;
    $my_main{$STRATEGY}[0] = "EACH" ;
}
$my_main{"SG_NMOL"}[0] = $IGR ;
$my_main{"SG_NGROUP"}[0] = $IGR ;
$my_main{"SG_NCRYST"}[0] = 1 ;
$my_main{"SG_CRYST1"} = () ; 
$my_main{"SG_CRYST1"}[0] = join ( ' ', @{$my_main{"SG_LIST"}} ) ;

#    print " mys cryst1:", $my_main{"SG_CRYST1"}[0], " \n" ;
next ;

FILE:
    $my_main{"SG_NMOL"}[0] = shift ( @{$commands{$keyword}} )  ; 
my $STR = shift ( @{$commands{$keyword}} )  ; 
if ( length($STR) > 0 ) { $SEGM_DICT = $STR ; }
open ( TXT, $SEGM_DICT ) || die "FILE OPEN ERROR: >$SEGM_DICT< \n" ; 

$IGR = 0 ; @{$my_main{"SG_LIST"}} = () ;
while(<TXT>)
{
    $IGR++ ;
    if ( $IGR > $my_main{"SG_NMOL"}[0] ) { $IGR-- ; last ; }
    chomp ;
    my $SEGM = uc($_) ;
    if ( length($SEGM) > 0 ) 
    {
	push ( @{$my_main{"SG_LIST"}}, $SEGM );
	$GROUP = join ( '', "SG_GROUP" , $IGR ) ;
	$STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	@{$my_main{$GROUP}} = $SEGM ;
	$my_main{$STRATEGY}[0] = "EACH" ;
	$my_main{"SG_NGROUP"}[0] = $IGR ;
    }
    else
    {
	print "dictionary file does not contain enough segment names ? \n" ;
	last ;
    }
}
if ( $my_main{"SG_NMOL"}[0] > $IGR ) { $my_main{"SG_NMOL"}[0] = $IGR ; }
next ;

RFREE:
    $my_main{"DFR_RFREE"}[0] = uc(shift ( @{$commands{$keyword}} )) ; next ;

STRATEGY:
$fl_strategy = "TRUE" ;
push ( @all_strategy, @{$commands{$keyword}} ) ;
next ;

USE:
    $use_diffraction_file = "TRUE" ;
# print "length ", length(${$commands{$keyword}}[0]), 
#    "[${$commands{$keyword}}[0]]\n" ;
    if ( length(${$commands{$keyword}}[0]) > 1 )
    { $my_main{"FILE_MTZ"}[0] = shift ( @{$commands{$keyword}} ) ; } 
    next ;
}

my $MATCH = 0 ;
if ( $fl_cryst eq "TRUE" ) 
{
    $IGR = 0 ; my $WORD ; 
    foreach $WORD ( @all_crysts ) 
    {
	print "cryst <$WORD> \n" ;
	$IGR++ ;
	$GROUP = join ( '', "SG_CRYST" , $IGR ) ;
	
	@{$my_main{$GROUP}} = split( ' ', $WORD ) ;
	
    }
    $my_main{"SG_NCRYST"}[0] =  @all_crysts ;

    $IGR = 0 ; my $WORD ; 
    foreach $WORD ( @all_cryst_data ) 
    {
	print "cryst <$WORD> \n" ;
	$IGR++ ;
	$GROUP = join ( '', "CRYST" , $IGR, "_DATA" ) ;
	@{$my_main{$GROUP}} = split( ' ', $WORD ) ;
    }


    print "END number of crysts ", $my_main{"SG_NCRYST"}[0], "\n" ;
}

if ( $fl_group eq "TRUE" ) 
{
    $IGR = 0 ; my $WORD ; 
foreach $WORD ( @all_groups ) 
{
#    print "group <$WORD> \n" ;
    $IGR++ ;
    $GROUP = join ( '', "SG_GROUP" , $IGR ) ;
    
    @{$my_main{$GROUP}} = split( ' ', $WORD ) ;
    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
#    if ( $my_main{$GROUP} == 1 )
#    {  $my_main{$STRATEGY} = "NONE" ; }
    if ( @{$my_main{$GROUP}} < 5 )
    {  $my_main{$STRATEGY}[0] = "EACH" ; }
    else 
    {  $my_main{$STRATEGY}[0] = "ONE" ; }
}
    foreach $WORD ( @{$my_main{"SG_LIST"}} ) 
    {
#	print "TOP number of groups $IGR $WORD \n" ;
	my $MATCH = 0 ;
	my $MEMBER ;
	my $I ;
	for ( $I = 1; $I <= $IGR; $I++ )
	{
	    $GROUP = join ( '', "SG_GROUP" , $I ) ;
#	    print " $I i groups: $GROUP >> @{$my_main{$GROUP}}\n" ;
	    foreach $MEMBER ( @{$my_main{$GROUP}} )
	    {
		if ( $WORD =~m"$MEMBER" ) { $MATCH++ ; }
#					    print "$MATCH ; $MEMBER found in $I $GROUP\n" ; }
	    }
	}
	if ( $MATCH == 0 )
	{
	    $IGR++ ;
	    $GROUP = join ( '', "SG_GROUP" , $IGR ) ;
#	print "NEW NON-AVER GROUP in IGR $MATCH $IGR, $WORD \n" ;
	    @{$my_main{$GROUP}} = $WORD ;
	    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	    $my_main{$STRATEGY}[0] = "EACH" ; 
	}
    }
    
    $my_main{"SG_NGROUP"}[0] = $IGR ;
#	print "END number of groups ", $my_main{"SG_NGROUP"}[0], "\n" ;
}
if ( $fl_strategy eq "TRUE" ) 
{
    while ( scalar (@all_strategy) > 0 )
    {
	$IGR = shift ( @all_strategy ) ; 
	$GROUP = join ( '', "SG_GROUP" , $IGR ) ;
	if ( $IGR > $my_main{"SG_NGROUP"}[0] || !exists ( $my_main{$GROUP} ) )
	{
	    print " a non-existing group $IGR requested? \n" ;
	    $PROC_ERROR = "TRUE" ;
	}
	else
	{
	    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	    $my_main{$STRATEGY}[0] = uc ( shift ( @all_strategy ) ) ;
	    if ( $my_main{$STRATEGY}[0] eq "LINK" ) 
	    {
		push ( @{$my_main{$STRATEGY}},  uc (shift ( @all_strategy )) ) ;
	    }
	}
    }
}

if ( $PROC_ERROR eq "TRUE" ) { exit ; }

$IGR =  $my_main{"SG_NGROUP"}[0] ;
while ( $IGR > 0 ) 
{
    $IGR++ ;
#    print "2222 XXXXX\n";
    $GROUP= join ( '', "SG_GROUP" , $IGR ) ;
    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
#    print $IGR, " GROUP: ", $GROUP, "\n" ;
#    print "{", @{$my_main{$GROUP}}, "} STR: ", $STRATEGY, @{$my_main{$STRATEGY}}, "\n" ;
#    my $LINE = join (" ", $IGR, @{$my_main{$STRATEGY}}, '|', @{$my_main{$GROUP}},  ) ;
    if ( exists($my_main{$GROUP} ) )  
    { 
	delete $my_main{$GROUP} ; 
	delete $my_main{$STRATEGY} ; 
    }
    else
    { 
#	print "else $IGR \n" ;
	last ; 
    }
}


#######################################

# print " SAVING FILE:::\n" ;
$conf_file = "main_config.data" ; 
main_config::write_main_config_file ( $conf_file, %my_main ) ; 

if ( $doit eq "FALSE" )  { exit ; }

######################################

my $macro_file ;

if ( $use_diffraction_file eq "TRUE" )  
{
    if ( $my_main{"FILE_MTZ"}[0] =~ "\.mtz" ) 
    {
	$macro_file = join ('', $ENV{"MAIN_CONF"}, "use_mtz.pl" ) ; 
	system ( "$macro_file --doit" ) ; 
    }
    if ( $my_main{"FILE_MTZ"}[0] =~ "\.sca" ) 
    {
	$macro_file = $ENV{"MAIN_CONF"} . "use_sca.pl" . " -f " . $my_main{"FILE_MTZ"}[0] ; 
	system ( "$macro_file --doit" ) ; 
    }
}
if ( $my_main{"AUTO_START"}[0] eq "ON" ) 
{
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_auto_start.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
}
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_read.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_save_file.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_restore_file.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
#$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_re_image.pl" ) ; 
#              system ( "$macro_file --doit" ) ; 
main_config::create_re_image ( %my_main ) ;

$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_symmetry.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_symmetry_ca.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_refine.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_refine_b.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_gen_solv.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_make_masks.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_score_map.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_dm_prep.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_dm_next.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_dm_loop.pl" ) ; 
              system ( "$macro_file --doit" ) ; 

if ( ${$my_main{"SG_NMOL"}}[0] > ${$my_main{"SG_NGROUP"}}[0] ) 
{	    
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_load_nmol.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_rms_fit.pl" ) ; 
              system ( "$macro_file --doit" ) ; 
$macro_file = join ('', $ENV{"MAIN_CONF"}, "create_create_all_others.pl" ) ; 
              system ( "$macro_file --doit" ) ; 

}

print << "END_OF_TEXT" ;

MAIN configuration files have now been generated.  

Now type "mainps" to start your MAIN session or 
if you are not satisfied with the defaults 
adjust your input data using "create_read.pl" and other scripts.

END_OF_TEXT
