
###########################################################################
# Copyright (c) 1998, Jeffrey Glen Rennie
# All rights reserved.
###########################################################################
namespace eval config {
    variable defaults

    set configDataFile "confdata.tcl"

    set defaults [source defaults.tcl]

    set configDataTemplate {
###########################################################################
# confdata.tcl
# Configuration information for Web Smacker.
# Do not modify
###########################################################################
global configData
array set configData { % }

}

    variable controlList
    variable checkbuttonList
    variable entryList
    set radiobuttonList {
	rbBlock
	rbRemove
    }
    set checkbuttonList { 
	alwaysBlock
	useProxy
	filter
    }
    set entryList {
	port
	proxyHost
	proxyPort
	updateFrequency
	updateURL
    }
    set controlList [concat $entryList $checkbuttonList]

    variable cbmap
    set cbmap [list deselect select]

}

# num must be 0 or 1
proc config::SetCB { name num } {
    variable cbmap
    $name [lindex $cbmap $num]
}

proc config::SetEntry { name text } {
    $name delete 0 end
    $name insert 0 $text
}

proc config::UseShortNames { root } {
    upvar frFilterOpts frFilterOpts
    upvar frConOpts frConOpts
    upvar frProxyOpts frProxyOpts
    upvar frSubOpts frSubOpts
    upvar frBottom frBottom
    upvar rbRemove rbRemove
    upvar rbBlock rbBlock
    upvar btnConsole btnConsole

    variable controlList
    foreach control $controlList {
	upvar $control $control
    }

    set frFilterOpts [set root]frFilterOptions
    set frConOpts [set root]frConnectOptions    
    set frProxyOpts [set root]frProxyOptions
    set frSubOpts [set root]frSubOptions
    set frBottom [set root]frBottom

    set btnConsole [set root]btnConsole
    set alwaysBlock $frFilterOpts.cbBlockKnown
    set port $frConOpts.frPort.entPort
    set useProxy $frProxyOpts.cbUseProxy
    set proxyHost $frProxyOpts.frProxyHost.entHost
    set proxyPort $frProxyOpts.frProxyPort.entPort
    set updateFrequency $frSubOpts.frDay.entDay
    set updateURL $frSubOpts.frURL.entURL

    set rbBlock $frFilterOpts.rbBlock
    set rbRemove $frFilterOpts.rbRemove
    set filter [set root]cbFilter
}

proc config::InitDialog { root } {
    UseValues $root
    variable checkbuttonList
    variable entryList
    variable radiobuttonList

    UseShortNames $root
    foreach button $checkbuttonList {
	SetCB [set $button] $values($button)
    }
    foreach entry $entryList {
	SetEntry [set $entry] $values($entry)
    }
    if { $values(filterMode) == "filter" } {
	$rbRemove select
    } else {
	$rbBlock select
    }
    OnCheckFilter $root
    OnCheckProxy $root
}

proc config::DrawDialog { root callBack} {
    UseValues $root
    UseShortNames $root

    wm title $root "Configure Web Smacker"
#    wm geometry $root 350x400
    # wm resizable $root 0 0

    catch { destroy [set root]frTopEmpty }
    frame [set root]frTopEmpty -height 10

    set frFilterOpts [set root]frFilterOptions
    catch { destroy $frFilterOpts }
    catch { destroy [set root]cbFilter }
    checkbutton [set root]cbFilter \
	    -text "Filter web pages and remove advertising" \
	    -variable [set varValues](filter) \
	    -command [list config::OnCheckFilter $root]
    frame $frFilterOpts -borderwidth 2  \
	    -relief raised
    pack [set root]frTopEmpty [set root]cbFilter $frFilterOpts \
	    -anchor nw -padx 16 -fill both -side top
    radiobutton $frFilterOpts.rbBlock -variable [set varValues](filterMode) \
	    -text "Show broken picture where ad would be" \
	    -value block
    radiobutton $frFilterOpts.rbRemove -variable [set varValues](filterMode) \
	    -text "Remove ads entirely from page" \
	    -value filter
    checkbutton $frFilterOpts.cbBlockKnown -variable [set varValues](alwaysBlock) \
	    -text "Always block ads from known ad sources"
    pack $frFilterOpts.rbBlock $frFilterOpts.rbRemove \
	    $frFilterOpts.cbBlockKnown \
	    -side top -padx 6 -anchor nw

    catch { destroy [set root]frEmpty }
    frame [set root]frEmpty -height 15

    catch { destroy [set root]lblConnectionOptions }
    label [set root]lblConnectionOptions -text "Connection options:"
    set frConOpts [set root]frConnectOptions    
    catch { destroy $frConOpts}
    frame $frConOpts -borderwidth 2  \
	    -relief raised
    pack [set root]frEmpty [set root]lblConnectionOptions \
	    $frConOpts \
	    -anchor nw -padx 16 -fill both -side top
    
    frame $frConOpts.frPort
    pack $frConOpts.frPort -fill both
    label $frConOpts.frPort.lblPort \
	    -text "Run Web Smacker on this port:"
    set helloWorld "Hello World"
    entry $frConOpts.frPort.entPort -textvariable [set varValues](port)
    pack $frConOpts.frPort.lblPort \
	    -side left -padx 6 -anchor nw
    pack $frConOpts.frPort.entPort \
	    -side right -padx 6 -anchor nw

    set frProxyOpts [set root]frProxyOptions
    catch { destroy $frProxyOpts }
    frame $frProxyOpts -borderwidth 2  \
	    -relief raised
    pack $frProxyOpts -anchor nw -padx 16 -fill both

    checkbutton $frProxyOpts.cbUseProxy -variable [set varValues](useProxy) \
	    -text "Connect to another proxy server" \
	    -command [list config::OnCheckProxy $root]
    pack $frProxyOpts.cbUseProxy -side top -anchor nw

    frame $frProxyOpts.frProxyHost
    pack $frProxyOpts.frProxyHost -fill both
    label $frProxyOpts.frProxyHost.lblHost -text \
	    "Proxy Host:"
    entry $frProxyOpts.frProxyHost.entHost -textvariable [set varValues](proxyHost)
    pack $frProxyOpts.frProxyHost.lblHost \
	    -side left -padx 6 -anchor nw
    pack $frProxyOpts.frProxyHost.entHost \
	    -side right -padx 6 -anchor nw

    frame $frProxyOpts.frProxyPort
    pack $frProxyOpts.frProxyPort -fill both
    label $frProxyOpts.frProxyPort.lblPort -text \
	    "Proxy Port:"
    entry $frProxyOpts.frProxyPort.entPort -textvariable [set varValues](proxyPort)    
    pack $frProxyOpts.frProxyPort.lblPort \
	    -side left -padx 6 -anchor nw
    pack $frProxyOpts.frProxyPort.entPort \
	    -side right -padx 6 -anchor nw

    catch { destroy [set root]frEmpty3 }
    frame [set root]frEmpty3 -height 15
    catch { destroy [set root]lblSubOptions }
    label [set root]lblSubOptions -text "Subscription options:"
    catch { destroy [set root]frSubOptions}
    frame [set root]frSubOptions -borderwidth 2  \
	    -relief raised
    pack [set root]frEmpty3 [set root]lblSubOptions \
	    [set root]frSubOptions \
	    -anchor nw -padx 16 -fill both -side top

    set frSubOpts [set root]frSubOptions
    catch { destroy $frSubOpts.frDay }
    frame $frSubOpts.frDay
    pack $frSubOpts.frDay -side top
    label $frSubOpts.frDay.lblEvery -text "Update filters every "
    entry $frSubOpts.frDay.entDay -width 2 \
	    -textvariable [set varValues](updateFrequency)
    label $frSubOpts.frDay.lblDay -text " days from this URL:"
    pack $frSubOpts.frDay.lblEvery \
	    $frSubOpts.frDay.entDay \
	    $frSubOpts.frDay.lblDay \
	    -anchor nw -padx 0 -fill both -side left
    frame $frSubOpts.frURL
    pack $frSubOpts.frURL 
    entry $frSubOpts.frURL.entURL -textvariable [set varValues](updateURL)\
	    -width 35
    button $frSubOpts.frURL.btnUpdateNow \
	    -text "Update Now" -width 10 -height 1 \
	    -command subscribe::DownloadFilter
    pack $frSubOpts.frURL.entURL \
	    $frSubOpts.frURL.btnUpdateNow \
	    -fill x -side left -padx 6 -expand true

    catch {destroy [set root]lblCopyright }
    label [set root]lblCopyright -text "Copyright 1998, Jeffrey Glen Rennie" \
	    -font bold
    pack [set root]lblCopyright

    catch { destroy $btnConsole }
###########################################################################
# uncomment the next three lines for a debugging console
#    button $btnConsole -text "Show Console" \
#	    -command {console show}
#    pack $btnConsole -fill x -pady 4 -padx 7

    catch { destroy $frBottom }
    frame $frBottom -borderwidth 6
    pack $frBottom -fill x
    button $frBottom.btnOk -width 10 -text Ok \
	    -command [list config::OnOk $root $callBack]
    button $frBottom.btnCancel -width 10 -text Cancel \
	    -command [list config::OnCancel $root $callBack]
    button $frBottom.btnReset -width 10 -text "Use Defaults" \
	    -command [list config::OnUseDefaults $root]
    button $frBottom.btnShutDown -width 10 -text Shutdown \
	    -command [list config::OnShutdown $root]
    set listButtons [list \
	    $frBottom.btnShutDown $frBottom.btnReset \
	    $frBottom.btnCancel $frBottom.btnOk ]
    if [CanLaunchHelp] {
	button $frBottom.btnHelp -width 10 -text Help \
		-command config::LaunchHelp
	set listButtons [concat [list $frBottom.btnHelp] $listButtons]
    }
    eval pack $listButtons [list -expand true -side right -padx 4]
}

proc config::OnCheckFilter { root } {
    UseValues $root
    UseShortNames $root

    set state [lindex [list disabled normal] $values(filter)]

    set buttonList { rbBlock rbRemove alwaysBlock }
    foreach control $buttonList {
	[set $control] config -state $state
    }
}

proc config::OnCheckProxy { root } {
    UseValues $root
    UseShortNames $root

    set state [lindex [list disabled normal] $values(useProxy)]
    set fgcolor [lindex [list systemDisabledText systemWindowText] \
	    $values(useProxy)]
    set bgcolor [lindex [list systemButtonFace systemWindow] $values(useProxy)]

    set entryList { proxyHost proxyPort  }
    foreach control $entryList {
	[set $control] config -state $state -fg $fgcolor -bg $bgcolor
    }
    set labelList { frProxyHost.lblHost frProxyPort.lblPort }
    foreach label $labelList {
	$frProxyOpts.$label config -fg $fgcolor
    }
}

proc config::UseValues { root } {
    regsub -all {\.} $root _ tag
    set name [set tag]_values
    uplevel [list global $name]
    uplevel [list upvar 0 $name values]
    uplevel [list set varValues $name]
}

proc config::DoDialog { parentWnd arrayBindings callBack } {
    upvar $arrayBindings bindings
    # now duplicate this array and merge with defaults
    variable defaults
    UseValues $parentWnd
    array set values $defaults
    array set values [array get bindings]
    catch { wm withdraw $parentWnd }
    DrawDialog $parentWnd $callBack
    InitDialog $parentWnd
    wm deiconify $parentWnd
    wm protocol $parentWnd WM_DELETE_WINDOW \
	    [list config::OnShutdown $parentWnd]
    focus $parentWnd
}

proc config::OnUseDefaults { root } {
    variable defaults
    UseValues $root
    unset values
    array set values $defaults
    InitDialog $root
}

proc config::OnOk { root callBack } {
    UseValues $root
    wm withdraw $root
    $callBack [array get values]
    unset values
}

proc config::OnShutdown { root args } {
    UseValues $root
    messageBox::DoMessageBox "Shutdown Web Smacker?" \
	    "Are you sure you want to shut down Web Smacker?  \
	    You may have problems connecting to the internet." \
	    config::OnShutdownConfirm \
	    yesno
}

proc config::OnShutdownConfirm { args } {
    if { [llength $args] && [lindex $args 0] == "yes" } {
	exit
    }
}

proc config::OnCancel { root args } {
    UseValues $root
    wm withdraw $root
    unset values
}    

proc config::LoadConfigData { } {
    global configData
    variable defaults
    variable configDataFile

    if { ![file exists $configDataFile] } {
	array set configData $defaults
    } elseif [catch {
	source $configDataFile
	subscribe::SetURL $configData(updateURL)
	subscribe::SetRefreshDays $configData(updateFrequency)
    } errMessage] {
	dbg::puts config "Error sourcing $configDataFile: $errMessage"
    }
}

proc config::SaveConfigData { } {
    global configData
    variable configDataFile
    variable configDataTemplate

    regsub % $configDataTemplate [array get configData] fileContents
    if [ catch {
	set fileHandle [open $configDataFile w]
	puts $fileHandle $fileContents
	close $fileHandle
    } errMessage] {
	dbg::puts config "Error saving configuration: $errMessage"
    }
}

config::LoadConfigData

proc config::OnSaveData { values } {
    global configData
    array set configData $values
    subscribe::SetURL $configData(updateURL)
    subscribe::SetRefreshDays $configData(updateFrequency)
    SaveConfigData
}

proc config::DoConfigDialog { } {
    global configData
    DoDialog . configData config::OnSaveData
}
    
proc config::CanLaunchHelp { } {
    global tcl_platform
    expr { $tcl_platform(platform) == "windows" }
}

proc config::LaunchHelp { } {
    global tcl_platform
    if ![CanLaunchHelp] {
	error "LauchHelp not supported on $tcl_platform(platform)."
    }
    # else
    LaunchHelp_$tcl_platform(platform)
}

proc config::LaunchHelp_windows { } {
    exec start help.htm &
}

###########################################################################
# Copyright (c) 1998, Jeffrey Glen Rennie
# All rights reserved.
###########################################################################
