#!/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 $ICOLOR = 105 ;
my $ICOLOR_INCR = 5 ;
if ( $my_main{"SG_NMOL"}[0] > 4 ) { $ICOLOR = 90 } ;
if ( $my_main{"SG_NMOL"}[0] > 8 ) { $ICOLOR_INCR = 2 } ;

if ( !exists($my_main{"SYM_IMAGE"}  ) )  { push ( @{$my_main{"SYM_IMAGE"}} , "SPHERE" ) ; }
if ( !exists($my_main{"SYM_IMAGE_RAD"}  ) )  { push ( @{$my_main{"SYM_IMAGE_RAD"}} , 30.0 ) ; }
if ( !exists($my_main{"SYM_IMAGE_COLOR_BASE"}  ) )  { push ( @{$my_main{"SYM_IMAGE_COLOR_BASE"}} , $ICOLOR ) ; }
if ( !exists($my_main{"SYM_IMAGE_COLOR_INCR"}  ) )  { push ( @{$my_main{"SYM_IMAGE_COLOR_INCR"}} , $ICOLOR_INCR ) ; }
if ( !exists($my_main{"SYM_IMAGE_SELECTION"}  ) )  { push ( @{$my_main{"SYM_IMAGE_SELECTION"}} , "segm name WORK_SEGM" ) ; }
if ( !exists($my_main{"SYM_IMAGE_TRACE"}  ) )  { push ( @{$my_main{"SYM_IMAGE_TRACE"}} , "OFF" ) ; }
if ( !exists($my_main{"SYM_IMAGE_MATRIX"}  ) )  { push ( @{$my_main{"SYM_IMAGE_MATRIX"}}, "n" ) ; }
if ( !exists($my_main{"SYM_IMAGE_MATRIX_SHIFT"}  ) )  { push ( @{$my_main{"SYM_IMAGE_MATRIX_SHIFT"}} , 0, 0, 0 ) ; }

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

#print " sym image rad", ${$my_main{"SYM_IMAGE_RAD"}}[0], "\n" ;
my $ATOM_SPHERE = ${$my_main{"SYM_IMAGE_RAD"}}[0] ;

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

my $keyword ; 
foreach $keyword ( sort keys (%commands) ) 
{
#    print " $keyword \n" ;
    if ( $keyword eq 'h' || substr($keyword, 0,4) eq "help"   ) { goto HELP }
    if ( $keyword eq 'o' || substr($keyword, 0,6) eq "output" ) { goto OUTPUT }
    if ( $keyword eq 'c' || substr($keyword, 0,5) eq "color"  ) { goto COLOR }
    if ( $keyword eq 'i' || substr($keyword, 0,9) eq "increment" ) { goto INCREMENT }
    if ( $keyword eq 'r' || substr($keyword, 0,6) eq "radius" ) { goto RADIUS }
    if ( $keyword eq 'g' || substr($keyword, 0,5) eq "gener"  ) { goto GENER }
    if ( $keyword eq 's' || substr($keyword, 0,9) eq "selection"  ) { goto SELECTION }
    if ( $keyword eq 't' || substr($keyword, 0,5) eq "trace"  ) { goto TRACE }
    if ( $keyword eq 'm' || substr($keyword, 0,6) eq "matrix"  ) { goto MATRIX }
    if ( $keyword eq 'f' || substr($keyword, 0,5) eq "shift"  ) { goto SHIFT }
    if ( substr($keyword, 0,4) eq "doit" ) { $doit = "TRUE" ; next ; }
    print "unknown option >$keyword<\n" ; $PROC_ERROR = "TRUE" ;

  HELP: 
    print 
	"  -h|--help)       prints this message with available options and current status \n",
	"  -o|--output)     set file name of the created macro [$MACRO_FILE]\n", 
	"  -c|--color)      starting color index for molecules [@{$my_main{\"SYM_IMAGE_COLOR_BASE\"}}]\n",
	"  -i|--increment)  increment of next molecule color [@{$my_main{\"SYM_IMAGE_COLOR_INCR\"}}]]\n",
	"  -r|--radius)     symmetry generation in specified sphere radius\n",
        "                   around the last picked atom [ @{$my_main{\"SYM_IMAGE_RAD\"}}]\n",
	"  -m|--matrix)     symmetry matrix [1 - n] non number switches of matrix selection [@{$my_main{\"SYM_IMAGE_MATRIX\"}}]\n",
	"  -f|--shift)      symmetry matrix translation  [@{$my_main{\"SYM_IMAGE_MATRIX_SHIFT\"}}]\n",
	"  -g|--gener)      symmetry generation of symmetry mates\n",
	"                   by [SPHERE/NO_CUT/WHOLE/CLOSEST/EXACT]  current [@{$my_main{\"SYM_IMAGE\"}}]\n",
        "                   SPHERE: within a sphere of the above specified radius\n",
        "                   NO_CUT: evergy segment with at least an atom inside the specified radius\n",
        "                   CLOSEST: whole segments positioned closes to the last clicked atom\n",
        "                   WHOLE: whole segments positioned into the unit cell  \n",
        "                   EXACT: segments are cut and shiftd to fit exactly the unit cell edges \n",
	"  -s|--selection)  selection to be displayed [@{$my_main{\"SYM_IMAGE_SELECTION\"}}]\n",
	"  -t|--trace)      atom trace [OFF/CA-P] [@{$my_main{\"SYM_IMAGE_TRACE\"}}]\n",
	"     --doit)       create the macro\n" ;
    exit ;
  OUTPUT:  $MACRO_FILE = shift ( @{$commands{$keyword}} ) ; next ;
  COLOR:   $ICOLOR = shift ( @{$commands{$keyword}} ) ; next ;
  INCREMENT:  @{$my_main{"SYM_IMAGE_COLOR_INCR"}} = (shift ( @{$commands{$keyword}} )) ; next ;
  RADIUS:   @{$my_main{"SYM_IMAGE_RAD"}} = @{$commands{$keyword}} ; next ;
  GENER:   @{$my_main{"SYM_IMAGE"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  SELECTION:   @{$my_main{"SYM_IMAGE_SELECTION"}} = ( join (" ", @{$commands{$keyword}} )) ; next ;
  TRACE:   @{$my_main{"SYM_IMAGE_TRACE"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  MATRIX:  @{$my_main{"SYM_IMAGE_MATRIX"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  SHIFT:   @{$my_main{"SYM_IMAGE_MATRIX_SHIFT"}} = @{$commands{$keyword}} ; next ;

}
# print " proc error $PROC_ERROR \n" ;
# print " doit  $doit\n" ;
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" ; 

$ATOM_SPHERE =  ${$my_main{"SYM_IMAGE_RAD"}}[0] ;

my $SYMM_SELECTION ;
if ( $my_main{"SYM_IMAGE_TRACE"}[0] eq "OFF" )
{
    $SYMM_SELECTION = join (" ", @{$my_main{"SYM_IMAGE_SELECTION"}} ) ; 
}
else
{
    $SYMM_SELECTION = join (" ", @{$my_main{"SYM_IMAGE_SELECTION"}}, ".a atom name CA P" ) ; 
}
my $SYMM_OPERATORS = "" ;
my $ss = ${$my_main{"SYM_IMAGE_MATRIX"}}[0] ;
if ( $ss =~ '\d' )
{
    $SYMM_OPERATORS = join ( " ", "matrix", @{$my_main{"SYM_IMAGE_MATRIX"}}, "translat", @{$my_main{"SYM_IMAGE_MATRIX_SHIFT"}} ) ;
}

print " sym operators {$SYMM_OPERATORS}\n" ;

my $hydrogen_flag ;
if ( $my_main{"IMAGE_HYDRO"}[0] eq "ON" ) 
{ $hydrogen_flag = 1 ; } else { $hydrogen_flag = 0 ; }
my $hydrogen_text = "" ;
if ( $hydrogen_flag == 0 )
{
    $hydrogen_text = " .a .not atom name H* " ;
}

print MACRO  << "END_OF_TEXT" ;
subroutine char SEGMENTS 

if ( MIN_TETHER .eq. \"ON\" ) then 
 echo "%WARNING: tether is running - turned it off first to trace side chains" 
 return
end_if

 delete atom select segment name #* end

 key SYM_SEL select $SYMM_SELECTION $hydrogen_text end

END_OF_TEXT

#    print $my_main{"SYM_IMAGE"}[0], " sys_image< \n" ;


if ( $my_main{"SYM_IMAGE_TRACE"}[0] ne "OFF" )
{
print MACRO 
    "make bond  sele $SYMM_SELECTION end from residue = CA\n",
    "make bond  sele $SYMM_SELECTION end from residue = P\n",
    "delet bond select bond range 6.4 1000. end\n\n" ;
}

if ( $my_main{"SYM_IMAGE"}[0] eq "SPHERE" ||  $my_main{"SYM_IMAGE"}[0] eq "NO_CUT")
{ print MACRO " set vari ATOM_SPHERE real = $ATOM_SPHERE \n\n" ; }


if ( $my_main{"SG_NMOL"} == 1 )
{
print MACRO " key old select all end\n" ;
print MACRO " image group name SYMMETRY\n" ;

if ( $my_main{"SYM_IMAGE"}[0] eq "SPHERE" )
{ print MACRO
    " symm select SYMM_SEL end around center atom \$1  \\\n",
      "   dist ATOM_SPHERE neigh 2 $SYMM_OPERATORS \n" ;
} 
elsif ( $my_main{"SYM_IMAGE"}[0] eq "WHOLE" )
{ print MACRO
      "symm select SYM_SEL end cell ( whole ) $SYMM_OPERATORS\n";
} 
elsif ( $my_main{"SYM_IMAGE"}[0] eq "CLOSEST" )
{ print MACRO
      "symm sele SYM_SEL end cell ( close sele atom numb $1 end ) $SYMM_OPERATORS\n";
}
elsif ( $my_main{"SYM_IMAGE"}[0] eq "EXACT" )
{ print MACRO
      "symm sele SYM_SEL end cell ( cut ) $SYMM_OPERATORS\n";
}
 print MACRO
    " key SYMM_M select .not old end \n",
    " image select SYMM_M end col $ICOLOR bond \n",
    " image select SYMM_M .a .not by bond all end col $ICOLOR atom cros\n\n";
}
else
{
    my $segm ; my $swat ;
    foreach $segm ( @{$my_main{"SG_LIST"}} )
    {
	if ( $segm eq "WAT" ) { $swat = "WAT*" ; } else { $swat = $segm ; }
	print MACRO " image group name SYM_", $swat, "\n" ;
	print MACRO " key old select all end \n" ;
if ( $my_main{"SYM_IMAGE"}[0] eq "SPHERE" )
{ print MACRO
     " symm select segment name $swat .a SYM_SEL end around \\\n", 
      "  center atom \$1 dist ATOM_SPHERE neigh 2  $SYMM_OPERATORS\n";
} 
elsif ( $my_main{"SYM_IMAGE"}[0] eq "WHOLE" )
{ print MACRO
      "symm select segment name $swat .a SYM_SEL end cell whole $SYMM_OPERATORS\n";
} 
elsif ( $my_main{"SYM_IMAGE"}[0] eq "CLOSEST" )
{ print MACRO
      "symm sele segm name $swat .a SYM_SEL end \\\n", 
      "      cell ( close sele atom numb \$1 end )  $SYMM_OPERATORS\n";
}
elsif ( $my_main{"SYM_IMAGE"}[0] eq "EXACT" )
{ print MACRO
      "symm sele segm name $swat .a SYM_SEL end \\\n", 
      "      cell ( cut ) $SYMM_OPERATORS\n";
}
elsif ( $my_main{"SYM_IMAGE"}[0] eq "NO_CUT" )
{ print MACRO
    " symm select SYM_SEL end around sele active end  \\\n",
      "   dist ATOM_SPHERE neigh 2 delete ( by segm ) $SYMM_OPERATORS\n" ;
}

my $SEGM_NAME = join ('', "\#", $swat ) ;
	print MACRO
	    " key SYMM_M sele .not old end \n",
    " rena select SYMM_M end segm $SEGM_NAME \n",
	    " image select SYMM_M end col $ICOLOR bond \n",
	    " image select SYMM_M .a .not by bond all end col $ICOLOR atom cros \n\n" ;
	$ICOLOR = $ICOLOR + $ICOLOR_INCR ;
    }
}
print MACRO " key old select all end \n" ;
if ( $my_main{"SYM_IMAGE"}[0] eq "SPHERE" )
{ print MACRO 
      " symm select segm name WAT end around center atom \$1 dist ATOM_SPHERE \\\n neigh 2 $SYMM_OPERATORS\n ";
}

if ( $my_main{"SYM_IMAGE_TRACE"}[0] ne "OFF" )
{
print MACRO 
    "\ndele bond  sele  $SYMM_SELECTION .a atom name CA P end \n\n",
}


print MACRO 
" key SYMM_WAT select .not old end \n",
" image select SYMM_WAT .and. atom name O* end col 125 atom cros \n\n",
"return \n";

close(MACRO) ;

exit ;

