-- チャット用クライアントのサンプル
-- Satofumi KAMIMURA
-- $Id: chat_sample.lua 354 2009-04-19 17:04:46Z satofumi $


-- 接続サーバ名の取得
local config = ConfigOption("chat_sample")
local server = config:server()
if #server == 0 then
   server = "localhost"
end
local port = config:port()
print("connecting to " .. server .. " (" .. port .. ")")


-- 接続
local client = GameClient()
if not client:connect(server, port) then
   -- 接続できなければ、メッセージを表示して終了する
   print("GameClient::connect: " .. client:what())
   os.exit(1)
end


-- 画面の作成
local screen = Screen()
local screen_rect = screen:rect()

local layer_manager = LayerManager()
local layer = Layer()
layer_manager:push_front(layer)

local offset = 16
local font_height = 24
local back_color = Color(0.0, 0.0, 0.4, 1.0)
local width = screen_rect.w - (offset * 2)
local message_height = font_height + offset
local log_height = screen_rect.h - (message_height + (offset * 3))

-- チャットメッセージ欄の作成
local log_rect = Rect(0, 0, width, log_height)
local log_back_surface = ColorSurface(log_rect, back_color)
local log_back = Label(log_back_surface)
log_back:setPosition(Point(offset, offset))

-- メッセージ入力欄の作成
local message_rect = Rect(0, 0, width, message_height)
local message_back_surface = ColorSurface(message_rect, back_color)
local message_back = Label(message_back_surface)
message_back:setPosition(Point(offset, screen_rect.h - message_height - offset))

layer:push_back(log_back)
layer:push_back(message_back)

-- 入力ハンドラの登録
local text_input = TextInput()
local backspace_event = CallbackEvent()
local dummy_unicode = 0
backspace_event:key(SDLK_BACKSPACE, SDL_KEYDOWN, KMOD_NONE, dummy_unicode)
text_input:setBackspaceEvent(backspace_event)
layer_manager:insertEvent(text_input);


-- イベントの登録
local quit_event = CallbackEvent()
setQuitEvent(quit_event)
layer_manager:insertEvent(quit_event)

local enter_event = CallbackEvent()
setEnterEvent(enter_event)
layer_manager:insertEvent(enter_event);


-- メッセージ描画用のフォント
local font = Font("resources/font.ttf", font_height, true)


-- 入力メッセージの描画
local input_text_surface = nil
local input_text = nil

local prompt_surface = ColorSurface(Rect(0, 0, 12, 2),
                                    Color(1.0, 1.0, 1.0, 1.0))
local prompt = Label(prompt_surface)
layer:push_front(prompt)

local base_y = screen_rect.h - message_height - offset / 2.0

function updateInputMessage(text)

   layer:remove(input_text)
   local position = Point(offset * 1.5, base_y)
   if #text > 0 then
      -- 入力文字列の描画
      input_text_surface = TextSurface(font, text)
      input_text = Label(input_text_surface)

      position = Point(offset * 1.5, base_y)
      input_text:setPosition(position)
      layer:push_front(input_text)

      position.x = position.x + input_text_surface:rect().w + 2
   end
   position.y = base_y + font_height;

   -- カーソルの描画
   prompt:setPosition(position)
end


-- 受信メッセージの描画
local chat_message_rect = Rect(0, 0, width - offset, log_height - offset)
local chat_message = ChatMessage(font, chat_message_rect)
chat_message:setPosition(Point(offset * 1.5, offset * 1.5))
layer:push_front(chat_message)

function drawMessage(message)

   chat_message:print(message)
   chat_message:newline()
end


-- メインループ
local quit = false
while not quit do

   layer_manager:updateEvent()

   if quit_event:isActive() then
      quit = true
   end

   -- 入力文字列の更新
   updateInputMessage(text_input:text())

   -- パケットの受信
   client:recv()

   -- 表示メッセージの更新
   while not client:empty() do
      local message = chatMessage(client:pop_packet())
      print(message)
      drawMessage(message)
   end

   if enter_event:isActive() then
      -- 入力済みメッセージの取得
      local message = text_input:text()
      text_input:clear()

      -- メッセージの送信
      if #message > 0 then
         client:push_packet(chatPacket(message))
         client:send()
      end
   end

   screen:clear()
   layer_manager:draw()
   layer_manager:swap()

   delay(10)
end

