/*!
  \file
  \brief レイヤー管理

  \author Satofumi KAMIMURA

  $Id: LayerManager.cpp 912 2009-05-20 14:10:37Z satofumi $

  \todo 登録済みのイベントを insertEvent() しても問題ないように修正する
*/

#include "LayerManager.h"
#include "Layer.h"
#include "EventManager.h"
#include "Event.h"
#include <boost/bind.hpp>
#include <algorithm>
#include <list>

using namespace qrk;
using namespace boost;
using namespace std;


namespace
{
  typedef list<LayerInterface*> Layers;
}


struct LayerManager::pImpl
{
  Layers layers_;
  EventManager event_manager_;

  Point<long> current_cursor_;
  Point<long> previous_cursor_;


  pImpl(void) : previous_cursor_(-1, -1)
  {
    SDL_EnableUNICODE(SDL_ENABLE);
  }


  ~pImpl(void)
  {
    SDL_EnableUNICODE(SDL_DISABLE);
  }


  static pImpl* object(void)
  {
    static pImpl singleton_object;
    return &singleton_object;
  }


  void updateEvent(void)
  {
    bool cursor_moved = false;
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      switch (event.type) {

      case SDL_QUIT:
        // !!! コールバックを呼ぶか、ここで終了させる
        exit(0);
        break;

      case SDL_KEYDOWN:
      case SDL_KEYUP:
        event_manager_.checkKey(event.key.keysym.sym, event.key.type,
                                event.key.keysym.mod, event.key.keysym.unicode);
        break;

      case SDL_MOUSEBUTTONDOWN:
      case SDL_MOUSEBUTTONUP:
        event_manager_.checkClick(event.button.button, event.button.type);
        break;

      case SDL_MOUSEMOTION:
        cursor_moved = true;
        current_cursor_ = Point<long>(event.motion.x, event.motion.y);
        event_manager_.checkEnterCursor(current_cursor_, previous_cursor_);
        previous_cursor_ = current_cursor_;
        event_manager_.cursorMoved();
        break;

      default:
        break;
      }
    }
  }


  void remove(LayerInterface* layer)
  {
    Layers::iterator it = find(layers_.begin(), layers_.end(), layer);
    if (it != layers_.end()) {
      layers_.erase(it);
    }
  }
};


LayerManager::LayerManager(void) : pimpl(pImpl::object())
{
}


LayerManager::~LayerManager(void)
{
}


void LayerManager::updateEvent(void)
{
  pimpl->updateEvent();
}


void LayerManager::draw(void)
{
  // 再描画
  for_each(pimpl->layers_.begin(), pimpl->layers_.end(),
           bind(&LayerInterface::draw, _1));
}


void LayerManager::swap(void)
{
  SDL_GL_SwapBuffers();
}


void LayerManager::clearEvent(void)
{
  pimpl->event_manager_.clear();
}


void LayerManager::insertEvent(Event* event)
{
  pimpl->event_manager_.insert(event);
}


void LayerManager::removeEvent(Event* event)
{
  pimpl->event_manager_.remove(event);
}


void LayerManager::clear(void)
{
  pimpl->layers_.clear();
}


void LayerManager::push_front(LayerInterface* layer)
{
  pimpl->layers_.push_front(layer);
}


void LayerManager::push_back(LayerInterface* layer)
{
  pimpl->layers_.push_front(layer);
}


void LayerManager::remove(LayerInterface* layer)
{
  pimpl->remove(layer);
}


Point<long> LayerManager::cursor(void)
{
  return pImpl::object()->current_cursor_;
}
