#
#  gpsman --- GPS Manager: a manager for GPS receiver data
#
#  Copyright (c) 2004 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: lowrance_patches.tcl
#  Last change:  15 March 2004
#
# this file contains patches to keep the Lowrance support code (in files
#  lowrance.tcl, lowrance_nmea.tcl, lowrance_symbols.tcl) compatible
#  with GPSMan after version 5.4.2
#

## possible sources of problems:
#   - proc StoreWP (know.tcl) can change the name of a WP; this may
#     have impact on the list of WP names of an incoming RT
#
#   - lowrance*.tcl not adequately protected against SRLFILE and SERIALPORT
#     being undefined
#

## symbols used by Magellan
#   from magellan.tcl Copyright (c) 2003 Matt Martin (matt.martin@ieee.org)
#   needed for importation/exportation of MapSend files (files_foreign.tcl)

set MAG_SYMTAB {WP_dot square_green house avn_vortac airport amusement_park
    casino car_repair boat camping exit 1st_aid avn_vordme buoy fuel deer
    golf lodging fish large_city light capitol_city boat_ramp medium_city
    museum danger park store knife_fork mountains diver_down_1 RV_park
    military scenic small_city oil_field stadium info truck_stop
    drinking_water wreck zoo}

## use of proc DestroyRGrabs (util.tcl) instead of the destroy command

proc CloseInProgrWindow {} {
    global ProgrWGrabs

    DestroyRGrabs .inprogr $ProgrWGrabs
    return
}

proc FailsInProgrWindow {mess} {
    # create dialog for signaling operation in progress
    # fail if window already exists
    #  single button: Abort; no bindings

    global COLOUR EPOSX EPOSY TXT ProgrWGrabs

    if { [winfo exists .inprogr] } { Raise .inprogr ; bell ; return 1 }
    set ProgrWGrabs [grab current]
    toplevel .inprogr
    wm protocol .inprogr WM_DELETE_WINDOW { bell }
    wm title .inprogr "GPS Manager: $TXT(commrec)"
    wm transient .inprogr
    wm geometry .inprogr +$EPOSX+$EPOSY

    frame .inprogr.fr -relief flat -borderwidth 5 -bg $COLOUR(messbg)
    label .inprogr.fr.title -text "..." -relief sunken
    label .inprogr.fr.text -text "$mess"
#    button .inprogr.fr.stop -text "STOP" -default active -command "NMEAOff"
    set fw .inprogr.fr.frc
    frame $fw -relief flat -borderwidth 0
    label $fw.tit -text "Working - please wait"
    button .inprogr.fr.ok -text "Stop" -state normal \
	-command NMEAOff
#    button .inprogr.fr.ok -text $TEXT(abort) -command NMEAOff
    pack $fw.tit -side left -padx 0
    pack .inprogr.fr -side top
    pack .inprogr.fr.title .inprogr.fr.text .inprogr.fr.frc \
	.inprogr.fr.ok -side top -pady 5
#    pack .inprogr.fr.stop -side top -pady 5
    update idletasks
    grab .inprogr.fr.ok
    RaiseWindow .inprogr
    return 0
}

## GPSMan RT identifiers can now be a string but Lowrance needs integers
proc SendData {command indx} {

    # transfer data to receiver
    # first group sent will be the Command Header. This will
    #  be followed by a data group for PUTS (& for some GETS) or will 
    #  trigger a reply header & data group for GETS.
    #  Second arg is the data index or zero, as appropriate. 

global WPName WPNum UnusedWPInx UnusedICInx RTWPoints RTList TRNumDeltas \
	PntCount NDeltas CMD CurrentTrack MESS RTIdNumber

    set data ""
    switch $command {
	GetWP -
	GetICpos - 
	GetRT -
	GetICgr {
	    set data [PacketHeader $CMD($command) 2]
	    lappend data [CheckSum $data]
	    set suffix [binary format "s" $indx]
	    set d [split $suffix ""]
	    lappend data [lindex $d 0] [lindex $d 1] 
	    lappend data [CheckSum $d]
	}    
	GetTR {
	    set data [PacketHeader $CMD($command) 1]
	    lappend data [CheckSum $data]
	    set suffix [binary format "c" $indx]
	    lappend data $suffix
	    lappend data [CheckSum $suffix]
	}
	GetTRd {
	    set deltaslice 20
	    set sdata [PacketHeader $CMD($command) 3]
	    lappend sdata [CheckSum $sdata]
	    set suffix [binary format "c" $indx]
	    if {$TRNumDeltas < $deltaslice} {
		set deltas [binary format "s" $TRNumDeltas]
		set TRNumDeltas 0
	    } else {
		set deltas [binary format "s" $deltaslice]
		set TRNumDeltas [expr ($TRNumDeltas - $deltaslice)]
	    }
	    set d [split $deltas ""]
	    lappend suffix [lindex $d 0] [lindex $d 1]
	    lappend suffix [CheckSum $suffix]
	    set data [concat $sdata $suffix]
	}
	PutWP {
	    if { $WPNum($indx) < 0} {
		set WPNum($indx) [lindex $UnusedWPInx 0]
		set UnusedWPInx [lreplace $UnusedWPInx 0 0]
	    }
	    set sdata [PacketHeader $CMD($command) 29]
	    lappend sdata [CheckSum $sdata]
	    set tvals [PrepData $command $indx]
	    set packdata [PackData $tvals]
	    lappend packdata [CheckSum $packdata]
	    set data [concat $sdata $packdata]
	}
	PutRT {
	    if { ! [regexp {^[0-9]+$} $RTIdNumber($ix)] } {
		GMMessage [format $MESS(cantsaveRTid) 1]
		return
	    }
	    set count [array size WPName]
	    set RTList ""
	    foreach pnt $RTWPoints($indx) {
		set inx [IndexNamed WP $pnt]
		if { ! [string compare WPNum($inx) "" ] } {
		    if { [llength $unusedWPInx] == 0 } {
			GMMessage $MESS(noWPinx)
			ResetCursor .
		    } else {
			set WPNum($inx) [lindex $UnusedWPInx 0]
			set UnusedWPInx [lreplace $UnusedWPInx 0 0]
		    }
		}
		lappend RTList $WPNum($inx)
	    }
	    set PntCount [llength $RTList]
	    set numbytes [expr ($PntCount * 2) + 16]
	    set data [PacketHeader $CMD($command) $numbytes]
	    lappend data [CheckSum $data]
	    set tvals [PrepData $command $indx]
	    set packdata [PackData $tvals]
	    set chk [CheckSum $packdata]
	    set packdata [concat $packdata [list $chk]]
	    set data [concat $data $packdata]
	}
	PutIC {
	    foreach i { $indx } {
		if { ! [string compare WPNum($i) "" ] } {
		    if { [llength $unusedICInx] == 0 } {
			GMMessage $MESS(noICinx)
			ResetCursor .
		    } else {
			set WPNum($i) [lindex $UnusedICInx 0]
			set UnusedICInx [lreplace $UnusedICInx 0 0]
		    }
		}
	    }
	    set count [llength $indx]
	    set data [PacketHeader $CMD(PutICno) 2]
	    lappend data [CheckSum $data]
	    set suffix [binary format "s" $count]
	    set d [split $suffix ""]
	    lappend data [lindex $d 0] [lindex $d 1] [CheckSum $d]
	    GPSInterface PutICno $data
	    for {set i 0} {$i < $count} {incr i} {
		set inx [lindex $indx $i]
 		set data [PacketHeader $CMD(PutIC) 11]
		lappend data [CheckSum $data]
		set tvals [PrepData $command $inx]
		set packdata [PackData $tvals]
		lappend packdata [CheckSum $packdata]
		set data [concat $data $packdata]
		GPSInterface $command $data
	    }
	    return
	}
	PutTR {
	    set CurrentTrack $indx
	    set sdata [PacketHeader $CMD($command) 11]
	    lappend sdata [CheckSum $sdata]
	    set tvals [PrepData $command $indx]
	    set packdata [PackData $tvals]
	    lappend packdata [CheckSum $packdata]
	    set data [concat $sdata $packdata]
	}
	PutTRd {
	    if {$PntCount < 40} {
		set NDeltas $PntCount
		set PntCount 0
	    } else {
		set NDeltas 40
		set PntCount [expr $PntCount - 40]
	    }
	    set n [expr $NDeltas * 4 + 3]
	    set data [PacketHeader $CMD($command) $n]
	    lappend data [CheckSum $data]
	    set tvals [PrepData $command $CurrentTrack]
	    set packdata [PackData $tvals]
	    lappend packdata [CheckSum $packdata]
	    set data [concat $data $packdata]
	}
	default {
	    set data [PacketHeader $CMD($command) 0]
	    lappend data [CheckSum $data]
	}
    }
    GPSInterface $command $data
    return
}

## change of proc PosType to array POSTYPE
## no need for position type in calls to proc CreatePos
## no need for SFilePFrmt

proc WriteHeader1 {file pformt fname} {
    # write header to file in GPSMan format, using $pformt for positions
    global TimeOffset Datum FCOMMAND CREATIONDATE \
	    SFilePFrmt SFileDatum SFileHeader MESS

    if {[file size $fname] ==0 } {
	puts $file "$FCOMMAND(comment) $MESS(written) GPSManager [NowTZ]"
	puts $file "$FCOMMAND(comment) $MESS(editrisk)"
	puts $file ""
	puts $file "$FCOMMAND(format) $pformt $TimeOffset $Datum"
	puts $file "$FCOMMAND(dates) $FCOMMAND($CREATIONDATE)"
	puts $file ""
    }
	set SFilePFrmt($file) $pformt
	set SFileDatum($file) $Datum
	set SFileHeader($file) 1
    }
    return
}

proc ConvWPData {d} {
    # convert WPs data got from receiver into list of lists suitable for
    #  use with SetItem
    global PositionFormat DEFAULTDISPOPT DATAFOR

    set wpnum [lindex $d 0]
    set wpname [lindex $d 4]
    set date [ConvLowrDate [lindex $d 5]]
    set s [lindex $d 1]
    set sym [NameForCodeOf SYMBOL $s]
    set p [CreatePos [lindex $d 2] [lindex $d 3] $PositionFormat "WGS 84"]
    set all [list Name Num Posn Date Symbol]
    set r [list $wpname $wpnum $p $date $sym]
    set r [FormData WP $all $r]
    return $r
}

proc ConvICData {d} {
    # convert Icon data got from receiver into list of lists suitable for
    #  use with SetItem
    global PositionFormat DEFAULTDISPOPT

    set id [lindex $d 0]
    set name [lindex $d 4]
    set p [CreatePos [lindex $d 1] [lindex $d 2] $PositionFormat "WGS 84"]
    set s [lindex $d 3]
    set sym [NameForCodeOf SYMBOL $s]
    set all [list Name Num Posn Symbol]
    set r [list $name $id $p $sym]
    set r [FormData WP $all $r]
    return $r
}

proc InDataTR {data} {
    # add TRs data from receiver to database

global Index Number GetDispl

    foreach p $data {
	set tps ""
	set f [lindex $p 0]
	set id [lindex  $f 0]
	set ix [IndexNamed TR $id]
	if {$ix == -1} then {
	    foreach d $p {
		set t [CreatePos [lindex $d 3] [lindex $d 4] \
			DMS "WGS 84"]
		lappend t [lindex $d 1] [lindex $d 2]
		lappend tps $t
	    }
	    set trdata [list [lindex $d 0] $tps]
	    set all [list Name TPoints]
	    set r [FormData TR $all $trdata]
	    StoreTR $ix $id $r $GetDispl
	}
    }
    return
}

proc NMEAInDataTR {id bulkdata} {
    # add TRs data from NMEA receiver to database

    global DataDefault NMEADatum Index Number GetDispl

    set DataDefault(TR) [list "" "" $NMEADatum "" "" 0]
    set tps ""
    set ix [IndexNamed TR $id]
    if {$ix == -1} then {
	foreach d $bulkdata {
	    set t [CreatePos [lindex $d 3] [lindex $d 4] \
			DMS $NMEADatum]
	    lappend t [lindex $d 1] [lindex $d 2]
	    lappend t [lindex $d 5] [lindex $d 6]
	    lappend tps $t
	}
	set trdata [list [lindex $d 0] $tps]
	set all [list Name TPoints]
	set r [FormData TR $all $trdata]
	StoreTR $ix $id $r $GetDispl
    }
    return
}



