/*!
  \file
  \brief モニタ対応の GPS 制御

  \author Satofumi KAMIMURA

  $Id: mGpsCtrl.cpp 1140 2009-07-13 21:41:41Z satofumi $
*/

#include "mGpsCtrl.h"
#include "GpsCtrl.h"
#include "GpsServer.h"
#include "SerialDevice.h"
#include "TcpipSocket.h"
#include "MonitorModeManager.h"
#include "MonitorEventScheduler.h"
#include "DeviceIpManager.h"
#include "mConnection.h"

using namespace qrk;


struct mGpsCtrl::pImpl
{
  MonitorModeManager::MonitorMode mode_;
  GpsCtrl gps_;
  Connection* monitor_con_;
  Connection* device_con_;


  pImpl(int argc, char *argv[])
    : monitor_con_(NULL), device_con_(NULL)
  {
    MonitorModeManager::object()->setMode(argc, argv);
    mode_ = MonitorModeManager::object()->mode();

    if (mode_ != MonitorModeManager::Simulation) {
      device_con_ = new SerialDevice;
    } else {
      device_con_ = new TcpipSocket;
    }
    monitor_con_ = new mConnection(device_con_);
    gps_.setConnection(monitor_con_);
  }


  ~pImpl(void)
  {
    if (monitor_con_) {
      delete monitor_con_;
    }
    if (device_con_) {
      delete device_con_;
    }
  }
};


mGpsCtrl::mGpsCtrl(int argc, char *argv[]) : pimpl(new pImpl(argc, argv))
{
}


mGpsCtrl::~mGpsCtrl(void)
{
}


const char* mGpsCtrl::what(void) const
{
  return pimpl->gps_.what();
}


bool mGpsCtrl::connect(const char* device, long baudrate)
{
  MonitorModeManager::MonitorMode Simulation = MonitorModeManager::Simulation;
  if (MonitorModeManager::object()->mode() == Simulation) {
    // device 名で IP ポート取得し、サーバを起動する
    long port = DeviceIpManager::object()->createIpPort(device);
    if (port > 0) {
      // IP ポートが取得済みでない場合のみ、サーバを起動する
      // !!! GPS 精度の情報を、引数で反映させるべき
      GpsServer* gps_server = new GpsServer;
      if (! gps_server->activate(port)) {
        // サーバが起動できなければ、接続を中断する
        return false;
      }
      MonitorEventScheduler::object()->registerDeviceServer(gps_server);
    }
  }

  return pimpl->gps_.connect(device, baudrate);
}


void mGpsCtrl::setConnection(Connection* con)
{
  pimpl->gps_.setConnection(con);
}


Connection* mGpsCtrl::connection(void)
{
  return pimpl->gps_.connection();
}


void mGpsCtrl::disconnect(void)
{
  pimpl->gps_.disconnect();
}


bool mGpsCtrl::isConnected(void)
{
  return pimpl->gps_.isConnected();
}


void mGpsCtrl::update(NmeaData* nmea)
{
  pimpl->gps_.update(nmea);
}
