//Copyright (C) 2000 - 2003 Thomas Schank 
// 
//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; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 

#ifndef _PROTOCOL_H
#define _PROTOCOL_H 

#include "link.h"
#include "packet.h"

#include "wpt_type.h"
#include "d103_wpt_type.h"
#include "d108_wpt_type.h"
#include "d109_wpt_type.h"

#include "rte_hdr_type.h"
#include "d200_rte_hdr_type.h"
#include "d201_rte_hdr_type.h"
#include "d202_rte_hdr_type.h"


#include "trk_hdr_type.h"
#include "d310_trk_hdr_type.h"
#include "trk_point_type.h"
#include "d300_trk_point_type.h"
#include "d301_trk_point_type.h"

#include "d600_date_time_type.h"

#include "product_data_type.h"
#include <iostream>


namespace gpspoint2 {
using namespace std;
using namespace gpspoint2;


/// structure to store garmin device information (product id and protocols)
struct DeviceInfo {
  /// data type
  ProductDataType pdt;
  /// device id
  int id;
  /// software version
  int software;
  /// device description
  string description;
  /// transfer capabilities
  bool waypointTransfer, routeTransfer, trackTransfer;
  /**
   * supported protocols
   * 0 = link protocol, 1 = command protocol, 2 = waypoint protocol
   * 4 = waypoint data protocol, 5 = route protocol, 6 = route header protocol
   * 7 = route data protocol, 8 = track protocol, 9 = track header protocol
   * 10 = track data protocol, 11 = proximity Protocol,
   * 12 = almanach protocol, 13 = almanach data protocol;
   */
  g_word protocols[14];

  /// creates an empty (id=0) device information structure
  DeviceInfo() {
    id = software = 0;
    description = "";
    for(int i = 0; i < 14; i++) protocols[i] = 0;
  }

  /// intializes device information structure
  DeviceInfo(ProductDataType dt, int i, int sw, const string &descr,
    bool wptTransfer, bool rteTransfer, bool trkTransfer,
      g_word p0, g_word p1, g_word p2, g_word p3, g_word p4,
      g_word p5, g_word p6, g_word p7, g_word p8, g_word p9,
      g_word p10, g_word p11, g_word p12, g_word p13) {
    pdt = dt; id = i; software = sw; description = descr;
    waypointTransfer = wptTransfer; routeTransfer = rteTransfer;
    trackTransfer = trkTransfer;
    protocols[0] = p0; protocols[1] = p1; protocols[2] = p2; protocols[3] = p3;
    protocols[4] = p4; protocols[5] = p5; protocols[6] = p6; protocols[7] = p7;
    protocols[8] = p8; protocols[9] = p9; protocols[10] = p10;
    protocols[11] = p11; protocols[12] = p12; protocols[13] = p13;
  }
};


/// this class chooses the right protocol for garmin data types such as waypoint, routepoints etc. 
class Protocol : Link 
{
   public:
      Protocol(void);   
      /// return information about connected device or 0 if connection
      /// to device failed
      const DeviceInfo *getInfo();

   protected:

      /// set which device to open 
      void setDevice(string s) { Link::setDevice(s); }

      /// open the port to garmin device, get garmin device info, set parameters etc....
      int openPort();

      /// open the port in 'raw' modus, 
      /// don't get any device info don't send or receive anything without explicit
      /// request
      int openPortRaw(){return Link::openPort();};

      /// close the device 
      void closePort(void){ Link::closePort(); clear();}
   
      /// Writes infomation to cout.
      void printTest(void);

      /// set Bauds 
      void setSpeed(string s) { Link::setSpeed(s); }

      /// receive one packet from the device and put it in p
      int getPacket(Packet &p) { return Link::getPacket(p);}

      /// send  packet p to the gps-device
      int sendPacket(Packet p){ return Link::sendPacket(p);}

      Date_Time_Type   * garmin_datetime;

      Wpt_Type * garmin_waypoint;

      Rte_Hdr_Type * garmin_routeheader;

      Trk_Hdr_Type * garmin_trackheader;
      Trk_Point_Type * garmin_trackpoint;


      bool  dateTimeTransfer;
      bool  waypointTransfer; 
      bool  routeHeaderTransfer;
      bool  trackHeader;
      bool  trackTransfer;
      bool  sendRouteLinkData;

   private:
      ProductDataType pdt;
      int product_ID;
      int softwareVersion;
      string productDescription;

      void setCapabilitiesByTable(void);
      void setCapabilitiesByPacket(Packet);

      
      void clear(void);
    
      g_word   linkProtocol, cmndProtocol,
               wptProtocol, wptDataProtocol,
               rteProtocol, rteHeaderProtocol, rteDataProtocol,
               trkProtocol, trkHeaderProtocol, trkDataProtocol,
               prxProtocol, prxDataProtocol,
               almProtocol, almDataProtocol;

};


}
#endif
