/*!
  \example chat_client.cpp
  \brief チャットサンプル (クライアント)

  \author Satofumi KAMIMURA

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

#include "port.h"
#include "PacketUtils.h"
#include "ChatPacketUtils.h"
#include "TcpipSocket.h"
#include "Screen.h"
#include "LayerManager.h"
#include "Layer.h"
#include "TextInput.h"
#include "CallbackEvent.h"
#include "EventUtils.h"
#include "luabindGeometry.h"
#include "luabindGui.h"
#include "luabindInit.h"
#include "LuaHandler.h"
#include "delay.h"
#include <luabind/luabind.hpp>
#include <iostream>

using namespace qrk;
using namespace luabind;
using namespace std;


namespace
{
  void initializeGui(lua_State* L, Layer &layer)
  {
    luabindGeometry(L);
    luabindGui(L);

    // GUI 画面を Lua スクリプトで作成
    LuaHandler::dofile(L, "chat_client.lua");

    try {
      call_function<Layer*>(L, "createForm", &layer);
    } catch (const error &e) {
      static_cast<void>(e);
      cout << "createForm(): " << lua_tostring(L, -1) << endl;
    }
  }


  void updateInputMessage(lua_State* L, Layer& layer, const string& text)
  {
    try {
      call_function<Layer*>(L, "updateInputMessage", &layer, text);
    } catch (const error &e) {
      static_cast<void>(e);
      cout << "updateInputMessage(): " << lua_tostring(L, -1) << endl;
    }
  }


  void addMessage(lua_State* L, const string message)
  {
    try {
      call_function<Layer*>(L, "addMessage", message);
    } catch (const error &e) {
      static_cast<void>(e);
      cout << "addMessage(): " << lua_tostring(L, -1) << endl;
    }
  }
}


int main(int argc, char *argv[])
{
  Screen screen;
  if (! screen.show(SDL_OPENGL)) {
    cout << "Screen::show(): " << screen.what() << endl;
    exit(1);
  }

  // GUI の初期化
  LayerManager layer_manager;
  Layer layer;
  layer_manager.push_front(&layer);

  lua_State* L = luabindInit();
  initializeGui(L, layer);
  updateInputMessage(L, layer, "");

  // 接続
  TcpipSocket client;
  if (! client.connect("localhost", Port)) {
    cout << "TcpipSocket::connect(): " << client.what() << endl;
    exit(1);
  }

  // イベントの登録
  CallbackEvent quit_event;
  setQuitEvent(&quit_event);
  layer_manager.insertEvent(&quit_event);

  CallbackEvent enter_event;
  setEnterEvent(&enter_event);
  layer_manager.insertEvent(&enter_event);

  TextInput text_input;
  CallbackEvent backspace_event;
  backspace_event.key(SDLK_BACKSPACE, SDL_KEYDOWN);
  text_input.setBackspaceEvent(&backspace_event);
  layer_manager.insertEvent(&text_input);

  // 制御ループ
  while (! quit_event.isActive()) {
    layer_manager.updateEvent();

    if (text_input.isChanged()) {
      // 入力メッセージの更新
      updateInputMessage(L, layer, text_input.text());
    }

    if (enter_event.isActive()) {
      // チャット用パケットの送信
      string message = text_input.text();
      if (! message.empty()) {
        Packet packet = chatPacket(message.c_str());
        PacketControl::send(packet, &client);
      }
      text_input.clear();
    }

    // パケットの受信
    Packet packet;
    if (PacketControl::receive(packet, &client)) {
      // 受信したメッセージを描画
      string message = chatMessage(packet);
      if (! message.empty()) {
        addMessage(L, chatMessage(packet));
      }
    }

    screen.clear();
    layer_manager.draw();
    layer_manager.swap();

    delay(10);
  }

  return 0;
}
