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

  \author Satofumi KAMIMURA

  $Id: mUsbJoystick.cpp 453 2009-01-06 12:21:24Z satofumi $

  \todo 引数に渡す index 番号も保存すべき
*/

#include "mUsbJoystick.h"
#include "UsbJoystick.h"
#include "MonitorDataHandler.h"
#include "LogNameHolder.h"

using namespace qrk;
using namespace std;


struct mUsbJoystick::pImpl
{
  MonitorModeManager::MonitorMode mode_;
  UsbJoystick joystick_;
  MonitorDataHandler* handler_;


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


  ~pImpl(void)
  {
    delete handler_;
  }


  const char* what(void)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      string message = joystick_.what();
      handler_->fetch(message);
      return message.c_str();

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return 0;

    } else {
      return joystick_.what();
    }
  }


  size_t joystickNum(void)
  {
    if (! handler_) {
      initializeHandler();
    }

    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      size_t joystick_num = joystick_.joystickNum();
      handler_->fetch(joystick_num);
      return joystick_num;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return 0;

    } else {
      return joystick_.joystickNum();
    }
  }


  void initializeHandler(void)
  {
    string log_name = LogNameHolder::object()->name("mUsbJoystick");
    mode_ = MonitorModeManager::object()->mode();
    handler_ = new MonitorDataHandler(log_name, mode_);
  }


  bool connect(int index)
  {
    if (! handler_) {
      initializeHandler();
    }

    // connect() については、return 情報のみ管理する
    if (mode_ == MonitorModeManager::Record) {
      bool ret = joystick_.connect(index);
      handler_->fetch(ret);
      return ret;

    } else if (mode_ == MonitorModeManager::Play) {
      bool ret = false;
      if (handler_->fetch(ret) < 0) {
        disconnect();
        return false;
      }
      return ret;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.connect(index);
    }
  }


  void disconnect(void)
  {
    joystick_.disconnect();
  }


  bool isConnected(void)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      bool ret = joystick_.isConnected();
      handler_->fetch(ret);
      return ret;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.isConnected();
    }
  }


  size_t numAxis(void)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      size_t num_axis = joystick_.numAxis();
      handler_->fetch(num_axis);
      return num_axis;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.numAxis();
    }
  }


  size_t numButtons(void)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      size_t num_buttons = joystick_.numButtons();
      handler_->fetch(num_buttons);
      return num_buttons;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.numButtons();
    }
  }


  short axisValue(size_t index)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      short axis_value = joystick_.axisValue(index);
      handler_->fetch(axis_value);
      return axis_value;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.axisValue(index);
    }
  }


  bool isButtonPressed(size_t index)
  {
    if ((mode_ == MonitorModeManager::Record) ||
        (mode_ == MonitorModeManager::Play)) {
      bool button_pressed = joystick_.isButtonPressed(index);
      handler_->fetch(button_pressed);
      return button_pressed;

    } else if (mode_ == MonitorModeManager::Simulation) {
      // !!!
      return false;

    } else {
      return joystick_.isButtonPressed(index);
    }
  }
};


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


const char* mUsbJoystick::what(void)
{
  return pimpl->what();
}


mUsbJoystick::~mUsbJoystick(void)
{
}


size_t mUsbJoystick::joystickNum(void)
{
  return pimpl->joystickNum();
}


void mUsbJoystick::setEvent(SDL_Event& event)
{
  pimpl->joystick_.setEvent(event);
}


bool mUsbJoystick::connect(int index)
{
  return pimpl->connect(index);
}


void mUsbJoystick::disconnect(void)
{
}


bool mUsbJoystick::isConnected(void)
{
  return pimpl->isConnected();
}


const char* mUsbJoystick::productInfo(void)
{
  // !!!
  return "Not implemented.";
}


size_t mUsbJoystick::numAxis(void)
{
  return pimpl->numAxis();
}


size_t mUsbJoystick::numButtons(void)
{
  return pimpl->numButtons();
}


short mUsbJoystick::axisValue(size_t index)
{
  return pimpl->axisValue(index);
}


bool mUsbJoystick::isButtonPressed(size_t index)
{
  return pimpl->isButtonPressed(index);
}
