/*!
  \file
  \brief 入力の受け付け

  \author Satofumi KAMIMURA

  $Id: InputHandler.cpp 717 2009-04-07 14:50:59Z satofumi $

  \todo カーソルが画面外にあるのを検出できるようにする
*/

#include "InputHandler.h"
#include <SDL.h>

using namespace qrk;


struct InputHandler::pImpl
{
  bool quit_event_;
  bool left_clicked_;
  bool right_clicked_;
  Point<long> cursor_position_;


  pImpl(void) : quit_event_(false)
  {
    clearEvent();
  }


  void clearEvent(void)
  {
    left_clicked_ = false;
    right_clicked_ = false;
  }


  void update(void)
  {
    clearEvent();

    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      switch (event.type) {
      case SDL_QUIT:
        quit_event_ = true;
        break;

      case SDL_KEYDOWN:
        keyPressed(event.key);
        break;

      case SDL_MOUSEBUTTONDOWN:
        mouseClicked();
        break;

      case SDL_MOUSEMOTION:
        cursorPosition();
        break;
      }
    }
  }


  void keyPressed(SDL_KeyboardEvent& key)
  {
    SDLKey sym = key.keysym.sym;
    SDLMod mod = key.keysym.mod;

    if (sym == SDLK_ESCAPE) {
      quit_event_ = true;

    } else if (mod & KMOD_CTRL) {
      if (sym == SDLK_q) {
        // Ctrl + q
        quit_event_ = true;
      }
    } else if (mod & KMOD_ALT) {
      if (sym == SDLK_F4) {
        // Alt + F4
        quit_event_ = true;
      }
    }
  }


  void mouseClicked(void)
  {
    Uint8 state = SDL_GetMouseState(NULL, NULL);
    left_clicked_ = state & SDL_BUTTON(SDL_BUTTON_LEFT);
    right_clicked_ = state & SDL_BUTTON(SDL_BUTTON_RIGHT);
  }


  void cursorPosition(void)
  {
    int x, y;
    SDL_GetMouseState(&x, &y);
    cursor_position_ = Point<long>(x, y);
  }
};


InputHandler::InputHandler(void) : pimpl(new pImpl)
{
}


InputHandler::~InputHandler(void)
{
}


void InputHandler::update(void)
{
  pimpl->update();
}


bool InputHandler::isQuit(void)
{
  return pimpl->quit_event_;
}


bool InputHandler::leftClicked(void)
{
  return pimpl->left_clicked_;
}


bool InputHandler::rightClicked(void)
{
  return pimpl->right_clicked_;
}


void InputHandler::setCursorPosition(const qrk::Point<long>& position)
{
  Uint16 x = position.x;
  Uint16 y = position.y;
  SDL_WarpMouse(x, y);
}


Point<long> InputHandler::cursorPosition(void)
{
  return pimpl->cursor_position_;
}
