#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'em-websocket'
require 'set'
require 'json'
require 'uri'

# WebSocket ポート
WS_PORT = 8804

# --- 変数定義 ---
clients = Set.new
participants = {}
team_points = Hash.new(0)
raised_queue = []
selected_url = nil

# --- ヘルパーメソッド ---
def broadcast_teams_and_points(clients, participants_hash, points_hash)
  team_list = participants_hash.values.sort_by { |p| [p[:group], p[:name]] }
  payload = { type: 'update_teams', teams: team_list, points: points_hash }.to_json
  clients.each { |c| c.send(payload) }
  puts "[BROADCAST] チームとポイント情報を更新しました。"
end

def broadcast_queue(clients, queue)
    payload = { type: "announce", queue: queue }.to_json
    clients.each { |c| c.send(payload) }
end

# --- サーバー起動 ---
trap('INT') do
  puts "\n[INTERRUPT] シャットダウン中..."
  EM.stop if EM.reactor_running?
end

puts "WebSocket Server starting on port #{WS_PORT}..."

EM.run do
  EM::WebSocket.start(host: "0.0.0.0", port: WS_PORT) do |ws_conn|
    
    # ▼▼▼【デバッグ用】▼▼▼
    # 接続が試みられた瞬間に、この中の処理が動きます。
    # 最も重要なのが ws_conn.onopen です。
    puts "[DEBUG] A connection was attempted. Waiting for 'onopen' event..."

    ws_conn.onopen do
      # ▼▼▼【デバッグ用】▼▼▼
      # このメッセージが表示されれば、WebSocketの接続が完全に成功したことになります。
      puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
      puts "!!! [SUCCESS] A client connected! 'onopen' triggered! !!!"
      puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

      clients << ws_conn
      ws_conn.send({ type: "info", message: "うっす！ WebSocket 接続完了" }.to_json)
      ws_conn.send({ type: 'update_teams', teams: participants.values.sort_by{|p| [p[:group], p[:name]]}, points: team_points }.to_json)
      ws_conn.send({ type: "announce", queue: raised_queue }.to_json)
      puts "[OPEN] クライアント接続: #{clients.size} 名"
    end
    
    ws_conn.onmessage do |msg|
      # ▼▼▼【デバッグ用】▼▼▼
      puts "[DEBUG] 'onmessage' triggered with message: #{msg}"
      
      puts "[RECV] #{msg}"
      # (onmessageの中身は変更なし)
      # ...
      begin
        data = JSON.parse(msg)
        case data["type"]
        when "join"
          participants[ws_conn] = { group: data["group"], name: data["name"] }
          puts "[JOIN] #{data['group']} の #{data['name']} さんが参加しました。"
          broadcast_teams_and_points(clients, participants, team_points)
        when "raise"
          participant_info = participants[ws_conn]
          if participant_info && !raised_queue.include?(participant_info)
            raised_queue << participant_info
            puts "[RAISE] #{participant_info[:group]} の #{participant_info[:name]} さんが挙手。"
            broadcast_queue(clients, raised_queue)
          end
        when "reset"
          raised_queue.clear
          puts "[RESET] 挙手者キューをリセットしました"
          broadcast_queue(clients, raised_queue)
        when "correct"
          if first_raiser = raised_queue.first
            group = first_raiser[:group]
            team_points[group] += 5
            puts "[CORRECT] #{group} に 5ポイント加算！ 合計: #{team_points[group]}点"
            payload = { type: "correct", answer: data["answer"], raiser: first_raiser }.to_json
            clients.each { |c| c.send(payload) }
            raised_queue.clear
            broadcast_teams_and_points(clients, participants, team_points)
            broadcast_queue(clients, raised_queue)
          end
        when "incorrect"
          if raised_queue.shift
             puts "[INCORRECT] 回答者がキューから削除されました。残り: #{raised_queue.size}名"
             clients.each { |c| c.send({type: "incorrect"}.to_json) }
             EM.add_timer(1) do
                puts "[TIMER] 1秒経過、更新されたキューを送信します。"
                broadcast_queue(clients, raised_queue)
             end
          end
        when "reset_scores"
          team_points.clear
          puts "[SCORE RESET] 全チームの得点をリセットしました。"
          broadcast_teams_and_points(clients, participants, team_points)
        when "adjust_score"
          group = data["group"]
          score = data["score"].to_i
          if group && score
            team_points[group] += score
            puts "[ADJUST SCORE] #{group} の得点を #{score}点 調整。合計: #{team_points[group]}点"
            broadcast_teams_and_points(clients, participants, team_points)
          end
        when "select"
          selected_url = "http://192.168.0.145:8890/#{URI.encode_uri_component(data["file"])}"
          clients.each { |c| c.send({ type: "select", url: selected_url }.to_json) }
        when "play"
          clients.each { |c| c.send({ type: "play" }.to_json) } if selected_url
        when "pause"
          clients.each { |c| c.send({ type: "pause" }.to_json) }
        when "stop"
          clients.each { |c| c.send({ type: "stop" }.to_json) }
        else
          puts "[WARN] 未知のメッセージタイプを受信: #{data['type']}"
        end
      rescue JSON::ParserError => e
        puts "[ERROR] JSONパースエラー: #{e.message}"
      end
    end

    ws_conn.onclose do
      # ▼▼▼【デバッグ用】▼▼▼
      puts "[DEBUG] 'onclose' triggered."

      clients.delete(ws_conn)
      # (oncloseの中身は変更なし)
      # ...
      if participant = participants.delete(ws_conn)
        puts "[LEAVE] #{participant[:group]} の #{participant[:name]} さんが退出しました。"
        raised_queue.delete(participant)
        broadcast_teams_and_points(clients, participants, team_points)
        broadcast_queue(clients, raised_queue)
      end
      puts "[CLOSE] 切断: 残り #{clients.size} 名"
    end

    # ▼▼▼【デバッグ用】▼▼▼
    # もしWebSocketの接続自体に何か問題があれば、ここにエラーが表示されます
    ws_conn.onerror do |error|
      puts "[ERROR] WebSocket error occurred: #{error.inspect}"
    end
  end
end
