#!/bin/sh  
# \
exec wish "$0" "$@"

set BASEVERSION 7.0.8

append githubPackages "alh camonitor medm probe StripTool"
append svnPackages "SDDS oagca SDDSepics oag"
append cvsPackages "adt AutoRoute beamUtil burt CAJMuxAppS35 CAJMuxAppThreaded condition ezca imageCatcher knobconfig rampload scopeutil sddsIDL"

if {[file exists /net/phoebus/epicsmgr/cvsroot]} {
    set env(CVSROOT) /net/phoebus/epicsmgr/cvsroot
} else {
    set env(CVSROOT) :ext:$env(USER)@challenger.aps.anl.gov:/net/phoebus/epicsmgr/cvsroot
    set env(CVS_RSH) ssh
}

proc Toggle {type} {
    global githubPackages
    global svnPackages
    global cvsPackages
    if {$type == "all"} {
        set value 1
    } else {
        set value 0
    }
    foreach package "$githubPackages $svnPackages $cvsPackages" {
        global $package
        set $package $value
    }
}

proc AddText {text} {
    global textwidget
    $textwidget insert end "${text}\n"
    $textwidget yview end
    update
} 

proc DownloadSoftware {args} {
    global BASEVERSION localBase
    global githubPackages
    global svnPackages
    global cvsPackages
    global env
    global textwidget
    
    $textwidget delete 1.0 end

    set overwrite no
    if {[file exists epics]} {
        AddText "ERROR: epics directory already exists."
        set overwrite [tk_messageBox -icon warning -type yesno -message "Do you wish to overwrite what you have previously checked out?"]
        if {$overwrite != "yes"} {
            return
        }
    }
    global oag
    if {$oag} {
        if {[file exists oag]} {
            if {$overwrite == "no"} {
                AddText "ERROR: oag directory already exists."
                set overwrite [tk_messageBox -icon warning -type yesno -message "Do you wish to overwrite what you have previously checked out?"]
                if {$overwrite != "yes"} {
                    return
                }
            }
        }
    }

    AddText "mkdir epics"
    file mkdir epics

    AddText "cd epics"
    cd epics

    if {$localBase} {
        AddText "wget -q https://epics.anl.gov/download/base/base-${BASEVERSION}.tar.gz"
        if {[catch {exec wget -q https://epics.anl.gov/download/base/base-${BASEVERSION}.tar.gz} results]} {
            set results [string trim $results]
            if {[llength $results] > 0} {
                #AddText "ERROR: $results"
                #return
            }
        }
        
        AddText "gzip -d base-${BASEVERSION}.tar.gz"
        exec gzip -d base-${BASEVERSION}.tar.gz
        
        AddText "tar -xf base-${BASEVERSION}.tar"
        exec tar -xf base-${BASEVERSION}.tar
        
        AddText "rm base-${BASEVERSION}.tar"
        file delete base-${BASEVERSION}.tar

        if {[file exists base]} {
            if {[file type base] == "link"} {
                file delete base
            } else {
                AddText "ERROR: Move existing epics/base out of the way."
                return
            }
        }
        if {$BASEVERSION == "7.0.4.1"} {
            AddText "ln -s base-R$BASEVERSION base"
            exec ln -s base-R$BASEVERSION base
        } else {
            AddText "ln -s base-$BASEVERSION base"
            exec ln -s base-$BASEVERSION base
        }
    } else {
        if {[file exists base]} {
            if {[file type base] == "link"} {
                file delete base
            } else {
                AddText "ERROR: Move existing epics/base out of the way."
                return
            }
        }
        AddText "ln -s /usr/local/oag/base base"
        exec ln -s /usr/local/oag/base base
    }
    if {($overwrite == "yes") && [file exists extensions]} {
        AddText "cd extensions"
        cd extensions

        AddText "get fetch"
        exec git fetch

        AddText "get reset --hard origin/master"
        exec git reset --hard origin/master

        AddText "cd .."
        cd ..
    } else {
        AddText "git clone https://github.com/epics-extensions/extensions"
        if {[catch {exec git clone -q https://github.com/epics-extensions/extensions} results]} {
            AddText "ERROR: $results"
            return
        }
    }

    AddText "cd extensions/src"
    cd extensions/src

    foreach package $githubPackages {
        global $package
        if {[set $package] == 1} {
            if {($overwrite == "yes") && [file exists $package]} {
                AddText "cd $package"
                cd $package
                
                AddText "get fetch"
                exec git fetch
                
                AddText "get reset --hard origin/master"
                exec git reset --hard origin/master
                
                AddText "cd .."
                cd ..
   
            } else {
                AddText "git clone https://github.com/epics-extensions/$package"
                if {[catch {exec git clone -q https://github.com/epics-extensions/$package} results]} {
                    AddText "ERROR: $results"
                    return
                }
            }
        }
    }

    foreach package $svnPackages {
        global $package
        if {[set $package] == 1} {
            if {$package == "oag"} {
                AddText "cd ../../.."
                cd ../../..

                if {[file exists oag/apps/src] && ($overwrite == "yes")} {
                    AddText "cd oag/apps/configure"
                    cd oag/apps/configure

                    AddText "svn revert -R ."
                    exec svn revert -R .

                    AddText "svn update"
                    exec svn update

                    if {[file exists .RELEASE.orig]} {
                        AddText "rm .RELEASE.orig"
                        file delete .RELEASE.orig
                    }

                    AddText "cd ../../.."
                    cd ../../..

                    AddText "cd oag/apps/src"
                    cd oag/apps/src

                    AddText "svn revert -R ."
                    exec svn revert -R .

                    AddText "svn update"
                    exec svn update

                    AddText "cd ../../.."
                    cd ../../..
                } else {
                    AddText "svn checkout https://svn.aps.anl.gov/AOP/oag/trunk oag --depth immediates"
                    exec svn checkout https://svn.aps.anl.gov/AOP/oag/trunk oag --depth immediates
                    
                    AddText "svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps oag/apps --depth immediates"
                    exec svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps oag/apps --depth immediates
                    
                    AddText "svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps/configure oag/apps/configure --depth infinity"
                    exec svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps/configure oag/apps/configure --depth infinity
                    
                    AddText "svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps/src oag/apps/src --depth immediates"
                    exec svn checkout https://svn.aps.anl.gov/AOP/oag/trunk/apps/src oag/apps/src --depth immediates
                    
                    AddText "cd oag/apps/src"
                    cd oag/apps/src
                    
                    AddText "svn update --set-depth exclude elegantTestSet"
                    exec svn update --set-depth exclude elegantTestSet
                    
                    set dirs [glob *]

                    foreach d $dirs {
                        if {[file isdirectory $d]} {
                            AddText "svn update --set-depth infinity $d"
                            catch {exec svn update --force --set-depth infinity $d}
                        }
                    }
                    
                    AddText "cd ../../.."
                    cd ../../..
                }
                AddText "cd epics/extensions/src"
                cd epics/extensions/src
            } else {
                if {[set $package] == 1} {
                    if {($overwrite == "yes") && [file exists $package]} {
                        AddText "cd $package"
                        cd $package
                        
                        AddText "svn revert -R ."
                        exec svn revert -R .
                        
                        AddText "svn update"
                        exec svn update
                        
                        AddText "cd .."
                        cd ..
                        
                    } else {
                        AddText "svn checkout https://svn.aps.anl.gov/AOP/${package}/trunk $package"
                        if {[catch {exec svn checkout https://svn.aps.anl.gov/AOP/${package}/trunk $package} results]} {
                            AddText "ERROR: $results"
                            return
                        }
                    }
                }
            }
        }
    }
    AddText "cd ../../.."
    cd ../../..
    
    set keyfixed 0
    foreach package $cvsPackages {
        global $package
        if {[set $package] == 1} {
            if {$keyfixed == 0} {
                if {[string range $env(CVSROOT) 0 3] == ":ext"} {
                    set i [string first "@" $env(CVSROOT)]
                    set hostname [string range $env(CVSROOT) [expr $i + 1] end]
                    set i [string first ":" $hostname]
                    set hostname [string range $hostname 0 [expr $i - 1]]
                    catch {exec ssh-keygen -R $hostname}
                    catch {exec ssh-keyscan -H $hostname >> $env(HOME)/.ssh/known_hosts}
                }
                set keyfixed 1
            }
            if {($overwrite == "yes") && [file exists epics/extensions/src/$package]} {
                AddText "cd epics/extensions/src/$package"
                cd epics/extensions/src/$package
                
                AddText "cvs update -C"
                exec cvs -q update -C
                
                AddText "cd ../../../.."
                cd ../../../..
            } else {
                AddText "cvs checkout epics/extensions/src/$package"
                if {[catch {exec cvs -q checkout epics/extensions/src/$package} results]} {
                    AddText "ERROR: $results"
                    return
                }
            }
        }
    }

    AddText "DONE DOWNLOADING"
}

proc ReadLine fd {
  if {[gets $fd line] < 0} {
    if {[eof $fd]} {
      catch {close $fd}
      set ::forever now
      return
    }
  }
  AddText $line
}

proc CompileBase {args} {
    global textwidget verbose cc ccc tcl_platform
    
    $textwidget delete 1.0 end
    AddText "cd epics/base/configure"
    cd epics/base/configure

    if {![file exists .CONFIG.orig]} {
	file copy -force CONFIG .CONFIG.orig
    } else {
	file copy -force .CONFIG.orig CONFIG
    }

    AddText "echo SHARED_LIBRARIES=NO >> CONFIG"
    exec echo SHARED_LIBRARIES=NO >> CONFIG
    
    AddText "echo LINKER_USE_RPATH=NO >> CONFIG"
    exec echo LINKER_USE_RPATH=NO >> CONFIG
    
    AddText "echo COMMANDLINE_LIBRARY= >> CONFIG"
    exec echo COMMANDLINE_LIBRARY= >> CONFIG
    
    AddText "echo CC=$cc >> CONFIG"
    exec echo CC=$cc >> CONFIG
    
    AddText "echo CCC=$ccc >> CONFIG"
    exec echo CCC=$ccc >> CONFIG
        
    if {$tcl_platform(os) == "Darwin"} {
	
	AddText "echo LDLIBS_READLINE= >> CONFIG"
	exec echo LDLIBS_READLINE= >> CONFIG

	AddText "echo \"OP_SYS_INCLUDES += -I/opt/local/include\" >> CONFIG"
	exec echo "OP_SYS_INCLUDES += -I/opt/local/include" >> CONFIG

	AddText "echo \"OP_SYS_LDFLAGS += \$(addprefix -L,\$(dir \$(firstword \$(wildcard /opt/local/lib/*))))\" >> CONFIG" 
	exec echo "OP_SYS_LDFLAGS += \$(addprefix -L,\$(dir \$(firstword \$(wildcard /opt/local/lib/*))))" >> CONFIG
	
    }

    AddText "cd .."
    cd ..

    AddText "make"
    if {$verbose} {
	set fd [open "| make -j4"]
    } else {
	set fd [open "| make -j4 -s -w"]
    }
    fconfigure $fd -blocking no
    fileevent $fd readable [list ReadLine $fd]
    vwait ::forever

    AddText "cd ../.."
    cd ../..

    AddText "DONE COMPILING EPICS/BASE"
}

proc CompileExtensions {args} {
    global githubPackages
    global svnPackages
    global cvsPackages
    global textwidget
    global env verbose
    eval global $githubPackages $svnPackages $cvsPackages
    
    set packages "$githubPackages $cvsPackages"

    $textwidget delete 1.0 end
    AddText "cd epics/extensions/configure"
    cd epics/extensions/configure

    AddText "make"
    set fd [open "| make"]
    fconfigure $fd -blocking no
    fileevent $fd readable [list ReadLine $fd]
    vwait ::forever

    AddText "cd ../src"
    cd ../src

    foreach package "SDDS oagca SDDSepics" {
        if {[set $package] == 1} {
            AddText "cd $package"
            cd $package
            
            AddText "make"
	    if {$verbose} {
		set fd [open "| make -j4 -k"]
	    } else {
		set fd [open "| make -j4 -s -w -k"]
	    }
            fconfigure $fd -blocking no
            fileevent $fd readable [list ReadLine $fd]
            vwait ::forever
            
            AddText "cd .."
            cd ..
        }
    }
    foreach package $packages {
        if {[set $package] == 1} {
            AddText "cd $package"
            cd $package
            
            AddText "make"
	    if {$verbose} {
		set fd [open "| make -j4"]
	    } else {
		set fd [open "| make -j4 -s -w"]
	    }
            fconfigure $fd -blocking no
            fileevent $fd readable [list ReadLine $fd]
            vwait ::forever
            
            AddText "cd .."
            cd ..
        }
    }

    AddText "cd ../../.."
    cd ../../..
    
    global oag
    if {$oag} {
	global tcl_platform
        set baseroot [pwd]/epics/base
        if {[info exists env(EPICS_HOST_ARCH)]} {
            set env(PATH) [pwd]/epics/extensions/bin/$env(EPICS_HOST_ARCH):$env(PATH)
        } elseif {$tcl_platform(os) == "Darwin"} {
            set env(PATH) [pwd]/epics/extensions/bin/darwin-x86:$env(PATH)
	} else {
            set env(PATH) [pwd]/epics/extensions/bin/linux-x86_64:$env(PATH)
        }
        AddText "cd oag/apps/configure"
        cd oag/apps/configure
        
	if {![file exists .RELEASE.orig]} {
	    file copy -force RELEASE .RELEASE.orig
	} else {
	    file copy -force .RELEASE.orig RELEASE
	}

	AddText "echo EPICS_BASE=$baseroot >> RELEASE"
	exec echo EPICS_BASE=$baseroot >> RELEASE

        AddText "make"
        set fd [open "| make"]
        fconfigure $fd -blocking no
        fileevent $fd readable [list ReadLine $fd]
        vwait ::forever
        
        AddText "cd ../src"
        cd ../src

        AddText "make"
	if {$verbose} {
	    set fd [open "| make -j4 -k"]
	} else {
	    set fd [open "| make -j4 -s -w -k"]
	}
        fconfigure $fd -blocking no
        fileevent $fd readable [list ReadLine $fd]
        vwait ::forever

        AddText "cd ../../.."
        cd ../../..

    }
    AddText "DONE COMPILING EPICS/EXTENSIONS"
}

set noCVS 0
if {[string range $env(CVSROOT) 0 3] == ":ext"} {
    set i [string first "@" $env(CVSROOT)]
    set hostname [string range $env(CVSROOT) [expr $i + 1] end]
    set i [string first ":" $hostname]
    set hostname [string range $hostname 0 [expr $i - 1]]
    if {[catch {exec ping -c 1 -W 2 challenger.aps.anl.gov} result]} {
        set noCVS 1
    }
}
set localBase 1
if {[file exist /usr/local/oag/base]} {
    set localBase 0
}

ttk::frame .frame
ttk::frame .frame.left
ttk::frame .frame.right
ttk::labelframe .frame.left.githubpackages -text "GitHub packages"
foreach package $githubPackages {
    set $package 1
    ttk::checkbutton .frame.left.githubpackages.cb$package -text $package -variable $package
    pack .frame.left.githubpackages.cb$package -anchor w
}
ttk::labelframe .frame.left.svnpackages -text "SVN packages"
foreach package $svnPackages {
    set $package 1
    ttk::checkbutton .frame.left.svnpackages.cb$package -text $package -variable $package
    pack .frame.left.svnpackages.cb$package -anchor w
}
ttk::labelframe .frame.left.cvspackages -text "CVS packages"
foreach package $cvsPackages {
    if {$noCVS} {
        set $package 0
    } else {
        set $package 1
    }
    ttk::checkbutton .frame.left.cvspackages.cb$package -text $package -variable $package
    pack .frame.left.cvspackages.cb$package -anchor w
}
pack .frame -fill both -expand true
pack .frame.left -side left -anchor nw
pack .frame.right -side left -fill both -expand true
pack .frame.left.svnpackages .frame.left.githubpackages .frame.left.cvspackages -anchor nw -fill x


eval font create smallFont [font actual TkDefaultFont]
set fontsize [font configure TkDefaultFont -size]
if {$fontsize < 0} {
    incr fontsize 2
} else {
    incr fontsize -3
}
font configure smallFont -size $fontsize
ttk::style configure Small.TButton -padding 2 -shiftrelief 0 -focusthickness 0 -width 0 -font smallFont

frame .frame.left.select
pack .frame.left.select -anchor nw
ttk::button .frame.left.select.all -text "ALL" -style Small.TButton -command "Toggle all"
ttk::button .frame.left.select.none -text "NONE" -style Small.TButton -command "Toggle none"
pack .frame.left.select.all .frame.left.select.none -side left

ttk::labelframe .frame.right.t -text "Info"
text .frame.right.t.text -yscrollcommand {.frame.right.t.s set} -wrap word
scrollbar .frame.right.t.s -command {.frame.right.t.text yview}
pack .frame.right.t -fill both -expand true
pack .frame.right.t.text -fill both -expand true -side left
pack .frame.right.t.s -fill y -side right
set textwidget .frame.right.t.text

ttk::frame .frame.right.options
pack .frame.right.options -anchor nw -fill x


set cc /usr/bin/gcc
set ccc /usr/bin/g++
if {[string range [info hostname] 0 3] == "cori"} {
    set cc cc
    set ccc CC
}
if {[string range [info hostname] 0 5] == "edison"} {
    set cc cc
    set ccc CC
}
if {$tcl_platform(os) == "Darwin"} {
    set cc "cc -mmacosx-version-min=10.12"
    set ccc "c++ -mmacosx-version-min=10.12"
}
set verbose 0

if {$localBase} {
    ttk::label .frame.right.options.labelbase -text "EPICS/Base Version:"
    ttk::entry .frame.right.options.entrybase -textvariable BASEVERSION
}
ttk::label .frame.right.options.labelcvs -text "CVSROOT:"
ttk::entry .frame.right.options.entrycvs -textvariable env(CVSROOT)
if {$localBase} {
    ttk::label .frame.right.options.labelcc -text "CC:"
    ttk::entry .frame.right.options.entrycc -textvariable cc
    ttk::label .frame.right.options.labelccc -text "CCC:"
    ttk::entry .frame.right.options.entryccc -textvariable ccc
}
ttk::label .frame.right.options.labelverbose -text "Verbose Compile:"
ttk::checkbutton .frame.right.options.entryverbose -variable verbose

if {$localBase} {
    grid .frame.right.options.labelbase -row 0 -column 0 -sticky e
    grid .frame.right.options.entrybase -row 0 -column 1 -sticky ew
}
grid .frame.right.options.labelcvs -row 1 -column 0 -sticky e
grid .frame.right.options.entrycvs -row 1 -column 1 -sticky ew
if {$localBase} {
    grid .frame.right.options.labelcc -row 2 -column 0 -sticky e
    grid .frame.right.options.entrycc -row 2 -column 1 -sticky ew
    grid .frame.right.options.labelccc -row 3 -column 0 -sticky e
    grid .frame.right.options.entryccc -row 3 -column 1 -sticky ew
}
grid .frame.right.options.labelverbose -row 4 -column 0 -sticky e
grid .frame.right.options.entryverbose -row 4 -column 1 -sticky w
grid columnconfigure .frame.right.options 1 -weight 1






ttk::frame .frame.right.buttons
pack .frame.right.buttons -anchor nw
ttk::button .frame.right.buttons.download -text Download -command DownloadSoftware
pack .frame.right.buttons.download -side left
if {$localBase} {
    ttk::button .frame.right.buttons.buildbase -text "Compile EPICS/Base" -command CompileBase
    pack .frame.right.buttons.buildbase -side left
}
ttk::button .frame.right.buttons.buildextensions -text "Compile EPICS/Extensions" -command CompileExtensions
pack .frame.right.buttons.buildextensions -side left

proc DisplayMessageAboutSystemPackages {} {
    global textwidget noCVS tcl_platform

    $textwidget insert 1.0 "Current directory is:\n[pwd]\n\nIf you have a preexisting epics/extensions that was not checked out from GitHub or this tool, please move it to epics/extensions.old first.\n\n"
    if {$tcl_platform(os) == "Linux"} {

	$textwidget insert end "Before compiling you should ensure that EPICS_HOST_ARCH is set and the following system packages are installed:\n\n"

	$textwidget insert end "Redhat/CentOS:\n"
	$textwidget insert end "wget git subversion cvs gzip tar make gcc gcc-c++ gcc-gfortran zlib-devel gd-devel libpng-devel libtiff-devel lapack-devel blas-devel gsl-devel openmotif-devel motif-devel libXaw-devel ncurses-devel readline-devel libXt-devel libXp-devel tcl-devel tk-devel hdf5-devel tktable\n\n"
	
	$textwidget insert end "Debian/Ubuntu:\n"
	$textwidget insert end "wget git subversion cvs gzip tar make gcc g++ gfortran zlib1g-dev libgd-xpm-dev libpng12-dev libtiff5-dev liblapack-dev libblas-dev libgsl0-dev libmotif-dev libxaw7-dev libncurses5-dev libreadline6-dev libxt-dev tcl-dev tk-dev libhdf5-serial-dev\n\n"
    } elseif {$tcl_platform(os) == "Darwin"} {
	$textwidget insert 1.0 "Before compiling you should ensure that EPICS_HOST_ARCH is set.\n\n"
    }
    
    if {$noCVS} {
        $textwidget insert end "You are outside the APS network which means that CVS repositories will not be available.\n"
    } else {
	if {![file exists /net/phoebus/epicsmgr/cvsroot]} {
	    $textwidget insert end "You will need passwordless ssh setup to checkout CVS repositories.\n"
	}
    }

}

DisplayMessageAboutSystemPackages

