# copyright (C) 1997-2006 Jean-Luc Fontaine (mailto:jfontain@free.fr)
# this program is free software: please read the COPYRIGHT file enclosed in this package or use the Help Copyright menu

# $Id: preferen.tcl,v 1.39 2006/03/05 00:45:44 jfontain Exp $


namespace eval preferences {
    # there is no knowledge in this file about which global variables are handled in preferences: only each folder namespace code
    # in the configuration interfeace knows and deals with them

    variable rcFileName ~/.moodssrc

    # return preferences variables in an array compatible name/value list:
    proc read "{rcFileName $rcFileName}" {                                             ;# allow overriding file name for daemon mode
        if {![file readable $rcFileName]} {
            return {}
        }
        set file [::open $rcFileName]
        set line [gets $file]                                                                                 ;# retrieve first line
        seek $file 0                                                                                                       ;# rewind
        set list {}
        if {![string match -nocase {<\?xml version=*} $line]} {                             ;# old data format (before version 16.8)
            while {[gets $file line] >= 0} {
                if {[string match #* $line]} continue                                                              ;# ignore comment
                foreach {name value} $line {
                    # moodss versions before 8.1 wrote fully qualified names (such as global::variable):
                    set name [namespace tail $name]
                    variable $name $value                                                            ;# initialize in this namespace
                    lappend list $name $value
                }
            }
        } elseif {[catch {set root [dom::parse [::read $file]]} message]} {                                            ;# XML format
            puts stderr "file $rcFileName is not a valid moodss preferences file:\n$message"
            exit 1
        } else {
            set document [dom::element cget [dom::document cget $root -documentElement] -tagName]                   ;# document type
            switch $document {
                moodssPreferences - moompsPreferences {
                    foreach node [dom::selectNode $root /$document/*] {
                        set name [dom::node cget $node -nodeName]
                        switch $name {
                            database {
                                set name databaseOptions
                                set value {}
                                foreach {option data} [array get [dom::node cget $node -attributes]] {
                                    lappend value -$option $data                        ;# heading dashes were stripped at save time
                                }
                            }
                            moodss {                                                ;# moodss version is saved in moomps preferences
                                set name moodssVersion
                                set value [dom::element getAttribute $node version]
                            }
                            viewerColors - smtpServers {
                                set value [listFromNode $node]
                            }
                            default {
                                set value [dom::node stringValue $node]
                            }
                        }
                        variable $name $value                                                        ;# initialize in this namespace
                        lappend list $name $value
                    }
                }
                default {
                    error "cannot handle $document type"
                }
            }
        }
        close $file
        return $list
    }

if {$global::withGUI} { ;# >8

    proc create {file parentPath} {
        if {[catch {
            close [open $file w]                                                                             ;# create an empty file
            # because of eventual embedded passwords, make sure file is readable by user only:
            file attributes $file -permissions rw-------
        } message]} {
            tk_messageBox -title moodss -parent $parentPath -type ok -default ok -icon error -message $message
            return 0
        } else {
            return 1
        }
    }

    proc save {variables {parentPath .}} {                                                                        ;# save to rc file
        # at this point, variables in this namespace have been updated in the configuration interface
        variable rcFileName

        set unix [string equal $::tcl_platform(platform) unix]
        if {$unix && ![file exists $rcFileName]} {                                                    ;# new file on a UNIX platform
            create $rcFileName $parentPath
        }
        if {[catch {::open $rcFileName w} file]} {
            tk_messageBox -title moodss -parent $parentPath -type ok -default ok -icon error -message $file
            return
        }
        lifoLabel::push $global::messenger [mc {saving preferences...}]
        ::update idletasks                                                                           ;# make sure message is visible
        set document [dom::create]
        set root [dom::document createElement $document moodssPreferences]
        dom::document createTextNode [dom::document createElement $root version] $global::applicationVersion
        set seconds [clock seconds]
        set date [clock format $seconds -format %D]; set time [clock format $seconds -format %T]
        dom::document createTextNode [dom::document createElement $root date] $date
        dom::document createTextNode [dom::document createElement $root time] $time
        foreach name $variables {
            # do not duplicate header data above and some other variables:
            switch $name {version - date - time - showToolBar - databaseOptions - viewerColors - smtpServers continue}
            dom::document createTextNode [dom::document createElement $root $name] [set ::preferences::$name]
        }
        nodeFromList $root viewerColors $::preferences::viewerColors                                               ;# list of colors
        nodeFromList $root smtpServers $::preferences::smtpServers                                    ;# list of SMTP output servers
        set node [dom::document createElement $root database]
        foreach {switch value} $::preferences::databaseOptions {
            # remove heading dash (invalid name start) and restore it later
            dom::element setAttribute $node [string trimleft $switch -] $value
        }
        # finally append variables not accessible directly via preferences interface:
        dom::document createTextNode [dom::document createElement $root showToolBar] $global::showToolBar
        dom::document configure $document -encoding [fconfigure $file -encoding]                  ;# use fine automatic Tcl encoding
        set data [serialize $document]
        dom::destroy $root                                                                                                ;# cleanup
        puts $file $data
        close $file
        if {\
            $unix && ($global::moompsResourceFile ne "") &&\
            ([file writable $global::moompsResourceFile] || ![file exists $global::moompsResourceFile])\
        } {                                                  ;# if moomps reference file is writable or does not yet exist, write it
            set created [file exists $global::moompsResourceFile]
            if {!$created} {                                                                                             ;# new file
                set created [create $global::moompsResourceFile $parentPath]
            }
            if {$created} {
                set file [::open $global::moompsResourceFile w]
                set document [dom::create]
                set root [dom::document createElement $document moompsPreferences]
                set node [dom::document createElement $root moodss]
                dom::element setAttribute $node version $global::applicationVersion
                dom::document createTextNode [dom::document createElement $root date] $date
                dom::document createTextNode [dom::document createElement $root time] $time
                dom::document createTextNode [dom::document createElement $root fromAddress] $::preferences::fromAddress
                nodeFromList $root smtpServers $::preferences::smtpServers                            ;# list of SMTP output servers
                set node [dom::document createElement $root database]
                foreach {switch value} $::preferences::databaseOptions {
                    # remove heading dash (invalid name start) and restore it later
                    dom::element setAttribute $node [string trimleft $switch -] $value
                }
                dom::document configure $document -encoding [fconfigure $file -encoding]          ;# use fine automatic Tcl encoding
                set data [serialize $document]
                dom::destroy $root                                                                                        ;# cleanup
                puts $file $data
                close $file
            }
        }
        lifoLabel::pop $global::messenger
    }

    proc update {} {                                        ;# update preferences saved in file with the current global state values
        array set data [read]
        set list [array names data]
        if {[llength $list] == 0} {                                                           ;# preferences were never before saved
            set list [configuration::variables 1]
            foreach name $list {                                                                   ;# initialize from default values
                if {![info exists ::preferences::$name]} {
                    set ::preferences::$name [set ::global::$name]
                }
            }
        }
        save $list
    }

} ;# >8

}
