#
#  gpsman --- GPS Manager: a manager for GPS receiver data
#
# Copyright (c) 1998-2009 Miguel Filgueiras mig@ncc.up.pt Universidade do Porto
#
#    This program is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License as published by
#      the Free Software Foundation; either version 2 of the License, or
#      (at your option) any later version.
#
#      This program is distributed in the hope that it will be useful,
#      but WITHOUT ANY WARRANTY; without even the implied warranty of
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#      GNU General Public License for more details.
#
#      You should have received a copy of the GNU General Public License
#      along with this program.
#
#  File: plugins.tcl
#  Last change:  20 December 2009
#

### which toplevels support plug-ins (used for documentation only)
# indices are patterns of toplevel window paths
# contents are lists of lists whose heads are widget types (button, menu)
#  and whose rests are sub-window paths (frame, menu) where the plug-in
#  widgets or entries will be inserted

  ## windows, procedures, title index in TXT, comment
  #   .         GMInit		GMtit		main window (map or lists)
  #   .gmWP*	GMWPoint	waypoint	WP edit/show windows
  #   .*.topc   GMTRCompute	TRcomp		TR computation window
  #   .gmRT*	GMRoute		route		RT edit/show windows
  #   .gmTR*	GMTrack		track		TR edit/show windows
  #   .gmLN*	GMLine		nameLN		LN edit/show windows
  #   .gmGR*	GMGroup		group		GR edit/show windows
array set PLGSWelcomed {
    .      {{menu fr.frm.top.frmap0.udefs.mn.plugin.exec
	          mpw.fr.frmi.frcoords.udefs.mn.plugin.exec}}
    .gmWP* {{button .fr.fr6}}
    .gmRT* {{button .fr.frdw}}
    .gmTR* {{button .fr.frdw}}
    .*.topc {{menu .fr.frsel.hgraph.mn.el .fr.frsel.hgraph.mn}}
    .gmLN* {{button .fr.frdw}}
    .gmGR* {{button .fr.frdw}}
}

# check for the following comments inserted in other source files
    # frame used for plug-ins (see array PLGSWelcomed, plugins.tcl)
    # menu used for plug-ins (see array PLGSWelcomed, plugins.tcl)
# call that must be made from procedures accepting plug-ins
#    AttachPlugIns $w


proc SetUpPlugIn {name where} {
    # make plug-in known to procedures setting up toplevel windows
    global PLGSForWindow

    foreach t $where {
	foreach {patt type widget} $t { break }
	set e [list $name $type $widget]
	if { [catch {set ts $PLGSForWindow($patt)}] } {
	    set PLGSForWindow($patt) [list $e]
	} else {
	    lappend ts $e
	    set PLGSForWindow($patt) $ts
	}
    }
    return
}

proc AttachPlugIns {hostwindow} {
    # make plug-ins available from window $hostwindow using information
    #  in the global array PLGSForWindow from first matched pattern
    # creates buttons and/or menu entries
    global PLUGIN PLGSForWindow

    foreach patt [array names PLGSForWindow] {
	if { [string match $patt $hostwindow] } {
	    foreach t $PLGSForWindow($patt) {
		foreach {plugin type sub} $t { break }
		# if sub-window does not exist do nothing
		set wd $hostwindow$sub
		if { ! [winfo exists $wd] } { continue }
		set pdata $PLUGIN($plugin)
		foreach {remark unavail params pcode} $pdata { break}
		if { [catch {set unavail [expr $unavail]} err] } { continue }
		if { $unavail } {
		    set state disabled
		} else { set state normal }
		set cmd ""
		append cmd PlugInExec " " "{$plugin}" " " $hostwindow " " \
		    [uplevel subst -nocommands \"$params\"]
		switch $type {
		    button {
			regsub -all { } $plugin "___" plref
			set b [button $wd.pl_$plref -text $plugin \
				   -command $cmd -state $state]
			BalloonBindings $b "{=$remark}"
			foreach {col row} [grid size $wd] { break }
			incr row -1
			grid $b -row $row -column $col -padx 10
		    }
		    menu {
			$wd add command -label $plugin -command $cmd \
			    -state $state
		    }
		}
	    }
	}
    }
    return
}

proc PlugInExec {plugin window args} {
    # execute plug-in called from $window
    #  $args is a list of consecutive elements NAME VALUE
    #    a variable NAME being set to VALUE before evaluation of
    #    the plug-in code
    global PLUGIN MESS

    foreach {v val} $args {
	if { [string index $v 0] != "_" } {
	    DisplayInfo [format $MESS(badpluginparamexec) $plugin $p]
	    return
	}
	set $v $val
    }
    if { [catch {eval [lindex $PLUGIN($plugin) 3]} err] } {
	DisplayInfo [format $MESS(pluginfailed) $plugin $err]
    }
    return
}

### predefined plug-ins
#  names and remarks must be in TXT

set PLUGIN($TXT(wptotwitter)) \
    [list $TXT(wptotwitternb) \
	 {[catch {package require TclCurl}]} \
	 {_ed $ed _ix $index} \
	 {   set _url http://twitter.com/statuses/update.xml
	     set _mess "#GPSMan #waypoint\n"
	     if { $_ed } {
		 global GMEd ChangedPosn
		 set _p [PosnGetCheck .gmWP.fr.frp.frp1 $GMEd(WP,Datum) \
			     GMMessage ChangedPosn]
		 if { $_p != "nil" } {
		     set _alt [AltitudeList \
				   [string trim [.gmWP.fr.fr11.alt get]]]
		     if { $_alt == "nil" } { set _alt "" }
		     set _datum $GMEd(WP,Datum)
		     set _name [.gmWP.fr.fr1.id get]
		     set _commt [.gmWP.fr.fr2.commt get]
		 }
	     } else {
		 global WPName WPPosn WPDatum WPAlt WPCommt
		 set _p $WPPosn($_ix) ; set _datum $WPDatum($_ix)
		 set _alt $WPAlt($_ix)
		 set _name $WPName($_ix) ; set _commt $WPCommt($_ix)
	     }
	     if { $_p != "nil" } {
		 global COUTFMT
		 set _lat [lindex $_p 0] ; set _long [lindex $_p 1]
		 append _mess lat= [format $COUTFMT(deg) [lindex $_p 0]] " " \
		     long= [format $COUTFMT(deg) [lindex $_p 1]]
		 if { $_alt != "" } {
		     append _mess "\nalt=" $_alt
		 }
		 append _mess "\ndatum=" [QuoteString $_datum]
		 if { $_name != "" } {
		     append _mess "\nname=" [QuoteString $_name]
		 }
		 if { $_commt != "" } {
		     append _mess "\ncomment=" [QuoteString $_commt]
		 }
		 WebPost Twitter 1 $_url status $_mess 140
	     }
	 } \
	 {{.gmWP* button .fr.fr6}}]

### set up predefined plug-ins and menu description

set PREDEFPLUGINDESCR {}
if { [catch {set uplugins [set $DefSpecs(plugin,ulist)]}] } {
    set uplugins {}
}

foreach plugin [lsort -dictionary [array names PLUGIN]] {
    if { [lsearch -exact $uplugins $plugin] == -1 } {
	if { [regexp {^(@|(---))} $plugin] } {
	    # avoid clashes with special denotations used by proc FillMenu
	    lappend PREDEFPLUGINDESCR " $plugin"
	} else { lappend PREDEFPLUGINDESCR $plugin }
	SetUpPlugIn $plugin [lindex $PLUGIN($plugin) end]
    }
}

