#!/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 ) ; 

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

if ( !exists($my_main{"OREF_IND_STEP"}  ) )  { push ( @{$my_main{"OREF_IND_STEP"}}, 20 ) ; }
if ( !exists($my_main{"PREF_TARGET"}  ) )  { push ( @{$my_main{"PREF_TARGET"}}, "ML" ) ; }
if ( !exists($my_main{"PREF_ML_MISSIN"}  ) )  { push ( @{$my_main{"PREF_ML_MISSIN"}}, 100 ) ; }
if ( !exists($my_main{"PREF_MAP_XTARG"}  ) )  { push ( @{$my_main{"PREF_MAP_XTARG"}}, 3 ) ; }
if ( !exists( $my_main{"DFR_RFREE"} ) ) { push ( @{$my_main{"DFR_RFREE"}}, "OFF" ) } ; 

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

my $MACRO_FILE = "refine_occ.cmds" ;
my $PROC_ERROR = "FALSE" ;
my $doit = "FALSE" ;

my $keyword ; 
foreach $keyword ( sort keys (%commands) ) 
{
    if ( $keyword eq 'h' || substr($keyword, 0,4) eq "help" ) { goto HELP }
    if ( $keyword eq 's' || substr($keyword, 0,4) eq "step" ) { goto STEP }
    if ( $keyword eq 't' || substr($keyword, 0,6) eq "target" ) { goto TARGET }
#    if ( $keyword eq 'a' || substr($keyword, 0,5) eq "atoms" ) { goto ATOMS }
#    if ( $keyword eq 'd' || substr($keyword, 0,4) eq "dens" ) { goto DENS }
#    if ( $keyword eq 'i' || substr($keyword, 0,4) eq "diff" ) { goto DIFF }
#    if ( $keyword eq 'r' || substr($keyword, 0,5) eq "ratio"  ) { goto RATIO }
#    if ( $keyword eq 'm' || substr($keyword, 0,3) eq "map"  ) { goto MAP }
#    if ( $keyword eq 'x' || substr($keyword, 0,4) eq "xmap" ) { goto XMAP }
    if ( $keyword eq 'q' || substr($keyword, 0,4) eq "qmap" ) { goto QMAP }

    if ( $keyword eq 'o' || substr($keyword, 0,6) eq "output" ) { goto OUTPUT }
    if ( substr($keyword, 0,4) eq "doit" ) { $doit = "TRUE" ; next ; }
    print "unknown option >$keyword<\n" ; $PROC_ERROR = "TRUE" ;

#  -a|--atoms)   missing atoms for estimation of ML [@{$my_main{"PREF_ML_MISSIN"}}]

  HELP:
    print << "END_OF_TEXT" ;
  -h|--help)    prints this message with available options and current status 
  -s|--step)    ind. Occupancy refinement  steps [-1 off; >0 on ] = [$my_main{"OREF_IND_STEP"}[0]]
  -t|--target)  target function for refinement [MAP/LSQ/ML/FREE_KICK]
                current [$my_main{"PREF_TARGET"}[0]]
  -o|--output)  set file name of the created macro [$MACRO_FILE]
     --doit)    create the macro
END_OF_TEXT
#  -q|--qmap)    MAP for rec. space refinement [@{$my_main{"PREF_MAP_XTARG"}}]
    exit ;
OUTPUT: $MACRO_FILE = shift ( @{$commands{$keyword}} ) ; next ;
STEP:    @{$my_main{"OREF_IND_STEP"}} = shift ( @{$commands{$keyword}} ) ; next ;
TARGET: @{$my_main{"PREF_TARGET"}} = shift ( @{$commands{$keyword}} ) ; next ;
#ATOMS:  @{$my_main{"PREF_ML_MISSIN"}} = shift ( @{$commands{$keyword}} ) ; next ;
#QMAP:  @{$my_main{"PREF_MAP_XTARG"}} = shift ( @{$commands{$keyword}} ) ; next ;
#RATIO: @{$my_main{"OREF_SCAL_XTARG"}} = shift ( @{$commands{$keyword}} ) ; next ;

#LSQ:    @{$my_main{"PREF_SCAL_XLSQ"}} = shift ( @{$commands{$keyword}} ) ; next ;
}

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

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


$conf_file = "main_config.data" ; 
main_config::write_main_config_file ( $conf_file, %my_main ) ; 

###  . ${MAIN_CONF}main_config.data.save.sh

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

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

print "creating \"$MACRO_FILE\" \n" ;
if ( -f $MACRO_FILE ) 
{ 
    my $back = join ('', $MACRO_FILE, ".old" ) ; 
    system ( "mv  $MACRO_FILE $back" ) ; 
}
open ( MACRO,  "> $MACRO_FILE" ) || die "FILE OPEN ERROR: >$MACRO_FILE< \n" ;
my $NZONES = ${$my_main{"MAP_ZONES"}}[0] ;

my $I = $my_main{"BREF_KICK_B0"}[0] ;
#print "if test 137 ", $I, $my_main{"BREF_STEP_COOL"}[0], "\n" ;
# if ( $I <= 0 && $my_main{"BREF_STEP_COOL"}[0] <= 0 )
# {
#     print << "END_OF_TEXT" ;
#     create_refine_b.pl> warning:: COLL STEPS [$my_main{"BREF_STEP_COOL"}[0]] and/or 
# 				    KICK VALUE [$my_main{"BREF_KICK_B0"}[0]] unspecified
# END_OF_TEXT
# }
my $BB_ADJ = $my_main{"BREF_SCAL_XTARG"}[0] ;
print MACRO << "END_OF_TEXT" ;
subroutine char SEGMENTS int THE_MAP 

! renames new waters to prevent deletions of already accepted solvents
rename segm WAT sele segm name WAT2 end  
set vari II int segm sele segm name WAT end
if ( II .gt. 0 ) then
set vari WORK_SEGM char global - 
    segm sele segm name WORK_SEGM .o segm name WAT end
end_if

set weight sele atom name H* .a segm name SEGMENTS end = 0.0 
set temp sele atom name H* .a segm name SEGMENTS end = 0.0 
set temp sele temp -0.1 0.1 .a .not atom name H* .a \\ 
    segm name SEGMENTS end = 25.0 ! resets Bs for rebuilt atoms


mini adjust ( bval = $BB_ADJ step = 40 )

END_OF_TEXT

######## NCS region definition

if ( @{$my_main{"SG_NMOL"}}[0] > @{$my_main{"SG_NGROUP"}}[0] )
{
    print MACRO
	"! defining COMPOSIT GROUPS by AUTO method \n" ;

    my ( $IGR, $GROUP, $STRATEGY );
    my $NCS_START = "FALSE" ;
    for ( $IGR = 1; $IGR <= @{$my_main{"SG_NGROUP"}}[0] ; $IGR++ )
    {
	$GROUP= join ( '', "SG_GROUP" , $IGR ) ;
	$STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	if ( $my_main{$STRATEGY}[0] ne "COMPOSIT" ) { next ; }
 #	print " groups: $IGR, <$GROUP> \n" ;
	if ( $NCS_START eq "FALSE" )
	{ 
	    print MACRO " define constr occ init\n" ;
	    $NCS_START = "TRUE" ;
	}
	print MACRO " define constr occ \( auto \\\n" ;
	my @lines = () ;
	my $MEMBER ; my $NC = 0; 
	foreach $MEMBER ( @{$my_main{$GROUP}} )
	{
	    $NC++ ;
#	print " member: $MEMBER> ", $NC, scalar(@{$my_main{$GROUP}}), "\n" ;
	    if ( $NC < @{$my_main{$GROUP}} )
	    {
		print MACRO "     sele segm name $MEMBER end \\\n" ;
	    }
	    else
	    {
		print MACRO "     sele segm name $MEMBER end \)\n\n" ;
	    }
	}
    }
}

print MACRO << "END_OF_TEXT" ;
 make map auto_grid 4.0 init cell real 
if ( MAP_LAST .lt. 0 ) return
set vari MAP_TARG int = MAP_LAST
make map from MAP_TARG init 0 real
if ( MAP_LAST .lt. 0 ) return
set vari MAP_PART int = MAP_LAST

make map MAP_PART atom symm -
           atom dens -
           sele segm name SEGMENTS .a weight 1.0 1000 end


 ener x-targ on \\ 
      x-targ map MAP_TARG \\
      x-targ scale = 100

END_OF_TEXT

my $REF_TARGET = $my_main{"PREF_TARGET"}[0] ;

print MACRO << "END_OF_TEXT" ;

 mini occupancy \\ 
      sele segm name SEGMENTS .a weigh 0.001 0.999 end \\ 
      step = $my_main{"OREF_IND_STEP"}[0] \\
END_OF_TEXT
if ( $my_main{"DFR_RFREE"}[0] eq "ON" )
{    
    if ( $REF_TARGET eq "FREE_KICK" ) 
    {
	print MACRO "     phase \( sele WORK_REFL end \\ \n" ; 
	print MACRO "            free sele WORK_REFL end \\ \n" ; 
	print MACRO "            test sele TEST end \\ \n" ; 
    }
    else
    {    
	print MACRO "     phase \( sele WORK_REFL end \\ \n" ; 
	print MACRO "            free sele TEST end \\ \n" ; 
    }
}
else
{ 
    print MACRO "    phase \( sele defined end \\ \n" ; 
    print MACRO "            free sele defined end \\ \n" ; 
}

    print MACRO " 	     part_map MAP_PART \\ \n" ; 

if ( $REF_TARGET eq "LSQ" )
{    print MACRO " 	     target ( least_square ) \\ \n" ; }
elsif ( $REF_TARGET eq "FREE_KICK" )
{
    my $KICK = $my_main{"PREF_ML_KICK"}[0] ;
    my $N_AVER = $my_main{"PREF_ML_AVER"}[0] ;
    print MACRO " 	     target ( free_kick $KICK $N_AVER ) \\ \n" ; 
}
elsif ( $REF_TARGET eq "ML" )
{    print MACRO " 	     target ( max_like 1 ) \\ \n" ; }
elsif ( $REF_TARGET eq "ML_EST" )
{    print MACRO " 	     target ( estim_ml missing @{$my_main{\"PREF_ML_MISSIN\"}}[0] ) \\ \n" ; }
elsif ( $REF_TARGET eq "ML_APR" )
{    print MACRO " 	     target ( aprox_ml ) \\ \n" ; }

    print MACRO << "END_OF_TEXT" ;
            ) \\ 
     writ = 1 
END_OF_TEXT

# kick # }

FINISH:
## echo after DONE ===================

if ( $my_main{"SG_NMOL"}[0] > $my_main{"SG_NGROUP"}[0] )
{ print MACRO "ener ncs off" } ;

print MACRO << "END_OF_TEXT" ;

delete map MAP_TARG
delete map MAP_PART
delete vari MAP_TARG

 ener  dens ( on map MAP_2FOFC poly 2 ) \\ 
       ncs off
mini adjust ( bond = @{$my_main{"PREF_SCAL_XTARG"}}[0] step = 100 )
mini posit writ 10 step 80
return
END_OF_TEXT
close (MACRO ) ;
