#!/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{"SKEL_CUSHION"} ) ) { push ( @{$my_main{"SKEL_CUSHION"}}, 15 ) } ; 
if ( !exists( $my_main{"SKEL_MAP"} ) ) { push ( @{$my_main{"SKEL_MAP"}}, "1" ) } ; 
if ( !exists( $my_main{"SKEL_DENSITY"} ) ) { push ( @{$my_main{"SKEL_DENSITY"}}, 0.8 ) } ; 
if ( !exists( $my_main{"SKEL_TOP_DENSITY"} ) ) { push ( @{$my_main{"SKEL_TOP_DENSITY"}}, 10.0 ) } ; 
if ( !exists( $my_main{"SKEL_SELECTION"} ) ) { push ( @{$my_main{"SKEL_SELECTION"}}, "ACTIVE" ) } ; 
if ( !exists( $my_main{"SKEL_RADII"} ) ) { push ( @{$my_main{"SKEL_RADII"}}, -1 ) } ; 

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

my $MACRO_FILE = "gen_skel.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 'o' || substr($keyword, 0,6) eq "output" ) { goto OUTPUT }
    if ( $keyword eq 'c' || substr($keyword, 0,7) eq "cushion" ) { goto CUSHION }
    if ( $keyword eq 'm' || substr($keyword, 0,3) eq "map" ) { goto MAP }
    if ( $keyword eq 'd' || substr($keyword, 0,7) eq "density" ) { goto DENSITY }
    if ( $keyword eq 't' || substr($keyword, 0,3) eq "top" ) { goto TOP }
    if ( $keyword eq 'r' || substr($keyword, 0,5) eq "radii" ) { goto RADII }
    if ( $keyword eq 's' || substr($keyword, 0,9) eq "selection" ) { goto SELECTION }
    if ( substr($keyword, 0,4) eq "doit" ) { $doit = "TRUE" ; next ; }
    print "unknown option >$keyword<\n" ; $PROC_ERROR = "TRUE" ;

HELP:
    print << "END_OF_TEXT" ;
  -h|--help)      prints this message with available options and current status 
  -o|--output)    file name of the created macro [$MACRO_FILE]
  -m|--map)       map skeletonization [1/2/3/4/5/6/7/8/9/10] [@{$my_main{"SKEL_MAP"}}]
  -d|--density)   density cut off low [@{$my_main{"SKEL_DENSITY"}}]
  -t|--top)       density cut off top [@{$my_main{"SKEL_TOP_DENSITY"}}]
  -c|--cushion)   cushion around the active atoms [@{$my_main{"SKEL_CUSHION"}}]
  -r|--radii)     atomic radii for mask (-1 means: not applicable) [@{$my_main{"SKEL_RADII"}}]
  -s|--selection) selection of atoms [HISTORY/ACTIVE/WORK_SEGM] [@{$my_main{"SKEL_SELECTION"}}]
     --doit)     create the macro "$MACRO_FILE"
END_OF_TEXT
    exit; 
OUTPUT: $MACRO_FILE = shift ( @{$commands{$keyword}} ) ; next ;

CUSHION: @{$my_main{"SKEL_CUSHION"}} = shift ( @{$commands{$keyword}} ) ; next ;
MAP: @{$my_main{"SKEL_MAP"}} = shift ( @{$commands{$keyword}} ) ; next ;
DENSITY: @{$my_main{"SKEL_DENSITY"}} = shift ( @{$commands{$keyword}} ) ; next ;
TOP: @{$my_main{"SKEL_TOP_DENSITY"}} = shift ( @{$commands{$keyword}} ) ; next ;
SELECTION: @{$my_main{"SKEL_SELECTION"}} = shift ( @{$commands{$keyword}} ) ; next ;
RADII: @{$my_main{"SKEL_RADII"}} = 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 ) ; 

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 $SK_CUSHION = $my_main{"SKEL_CUSHION"}[0] ;
my $MAP_DENSITY = $my_main{"SKEL_DENSITY"}[0] ;
my $MAP_TOP_DENSITY = $my_main{"SKEL_TOP_DENSITY"}[0] ;
my $MY_MAP = $my_main{"SKEL_MAP"}[0] ;
my $MY_SEL = $my_main{"SKEL_SELECTION"}[0] ;
my $MY_RADII = $my_main{"SKEL_RADII"}[0] ;

print MACRO << "END_OF_TEXT" ; 

! subroutine int SK_CUSHION

! MAP_ORIG = is a unit cell map
! MAP_SKL_DENS = points to the map which will be skeletonized, by default it
!          is the same as the MAP_ORIG
! CUT_OFF = demarks the lower density level till which the map will be skeletonized
! CUT_TOP = demarks the highest density level till which the map will be skeletonized
! SIZE_TOO_SMALL = designates the number of atoms in the connected sekelton
!                fragments below which atoms will be delited
! SIZE_MEDIUM = demarks the border in size between small an large skeleton
!             fragments to enable differentiating created fragments 
!             according to their size by color

set vari CUSHION int = $SK_CUSHION

set vari MAP_ORIG = $MY_MAP
set vari MAP_OLD = nmaps
set vari SIZE_TOO_SMALL = 10
set vari SIZE_MEDIUM = 100
set vari CUT_OFF real = $MAP_DENSITY
set vari CUT_TOP real = $MAP_TOP_DENSITY
!if ( RESOL_MAX .lt. 1.8 ) set vari CUT_TOP = 12
!if ( RESOL_MAX .lt. 1.5 ) set vari CUT_TOP = 15
!if ( RESOL_MAX .lt. 1.2 ) set vari CUT_TOP = 20
! normally you do not want to edit lines below

END_OF_TEXT

#    print " my sl:", $MY_SEL, "\n" ;

my  $SEL_TEXT ;
if ( $MY_SEL eq "HISTORY" ) { $SEL_TEXT = "key XX_KEY sele history end" ; }
if ( $MY_SEL eq "ACTIVE" ) { $SEL_TEXT = "key XX_KEY sele active end" ; }
if ( $MY_SEL eq "WORK_SEGM" ) { $SEL_TEXT = "key XX_KEY sele  segm name WORK_SEGM end" ; }

#print "$SEL_TEXT \n" ;
print MACRO "$SEL_TEXT\n" ;

print MACRO << "END_OF_TEXT" ; 

set vari I_ATOM integer = -1
set vari I_ATOM integer atom sele XX_KEY end

if ( I_ATOM .gt. 0 ) then

 make map from MAP_ORIG full init \\
      around CUSHION sele XX_KEY end
if ( MAP_LAST .lt. 0 ) return
set vari MAP_SKL_DENS int = MAP_LAST

END_OF_TEXT

if ( $MY_RADII > 0.01 )
{
print MACRO << "END_OF_TEXT" ; 
make map MAP_SKL_DENS empty
make map MAP_SKL_DENS atom ( mask $MY_RADII ) select XX_KEY end
END_OF_TEXT
}

print MACRO << "END_OF_TEXT" ; 
 make map MAP_SKL_DENS from MAP_ORIG copy


else

 make map from MAP_ORIG full init
if ( MAP_LAST .lt. 0 ) return
set vari MAP_SKL_DENS int = MAP_LAST
 make map MAP_SKL_DENS from MAP_ORIG copy
end_if


key XX_KEY drop

! ========= END OF HEADER =============
! usually there is no need to edit the lines below 
! -------------------------------------------------------------

set vari MAP_SKEL = MAP_SKL_DENS + 1
set vari MAP_CLOUD = MAP_SKEL + 1
! ------

set vari ITEST int = -1790
! set vari ITEST inte atom sele atom numb \$1 end
!	show vari ITEST

delete atom sele segm name SKEL #* end

key old sele all end

make map from MAP_SKL_DENS init 0 integer
if ( MAP_LAST .lt. 0 ) return
set vari MAP_SKEL int = MAP_LAST

make point init from map MAP_SKL_DENS extreme CUT_OFF CUT_TOP
make map MAP_SKEL from MAP_SKL_DENS local CUT_OFF CUT_TOP

! ------

make map from MAP_SKEL full integer init 
if ( MAP_LAST .lt. 0 ) return
set vari MAP_CLOUD int = MAP_LAST
    
make map MAP_CLOUD from MAP_SKEL copy
make map MAP_CLOUD cloud sele old end


! image col 220 poin dens numb

make point from map MAP_SKL_DENS saddle MAP_CLOUD MAP_SKEL ! test 304 331 
make atom from point ( reindex use_map MAP_CLOUD test ITEST ) 
key skeleton sele .not old end
! dele bond sele bond range 10. 1000. end

 dele atom sele .not by bond all .and skeleton end

make segm from atom sele skeleton end

! dele bond sele bond range 10. 1000. end
! dele atom sele .not old .a segm range 1 SIZE_TOO_SMALL end

! rena sele skeleton end atom CX
!set temp sele skeleton end = 50.
!set weigh sele skeleton end = 1.
rename chain X sele skeleton end

! Number of atoms per segment
!set col sele skeleton .a segm range 1 SIZE_MEDIUM end col 128
!set col sele skeleton .a segm range SIZE_MEDIUM  100000 end col 220
set col sele skeleton end = 220

image erase
key image sele .not all end
image group name TRACE_SKELET

image sele skeleton .a segm rang 10 100000 end set bond

rena segm SKEL sele skeleton end

delete map MAP_SKEL
delete map MAP_CLOUD
delete map MAP_SKL_DENS
<?MAIN_CMDS:use_atoms.cmds ACTIVE
key active sele skeleton end
return

END_OF_TEXT

close ( MACRO ) ;




