#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# EM Intro. - http://keijinsonyaban.blogspot.jp/2010/12/eventmachine.html
require 'em-websocket'
require 'json'
require 'csv'
PORT = 8804

clients = {}
ans = {}
readiness = {}

#<<<<<<< HEAD
#@musiclist = ["UFO.mp3"]
#=======
@musiclist = CSV.read("../public/audio/music.csv", :headers=>true)
#>>>>>>> cf891c544eeca563d1b75fdc33107a9a3a55512d
@musicpos  = 0
@rediness  = {}
@admin = nil
@stoptime = nil

p @musiclist[0]

print("No clients yet...")
EM::WebSocket.start({:host => "0.0.0.0", :port => PORT}) do |ws_conn|
  ws_conn.onopen do
    # p "hello"+ws_conn.inspect
    clients[ws_conn] = a = {}	# Start from NO NAME
    printf("%d guest(s)\n", clients.keys.length)
    a["ping"] = Time.now.to_f
    ws_conn.send("PING")
  end
  ws_conn.onmessage do |message|
    jv = JSON.parse(message)
    team, st = jv['team'], jv['state']
    if team > ''
      clients[ws_conn]["name"] = team
      if "PUSH" == st			# /PUSH: ([0-9.]+)/ =~ st
        ans[team] ||= []
        ans[team] << (jv['curtime']||9999)
        if @stoptime
          @stoptime = [@stoptime, jv['curtime']].min
        else
          @stoptime = jv['curtime']
        end
        STDERR.printf("Stopped at client %.3fs\n", @stoptime) if @stoptime
        p ans
      end
    end
    # clients.each{|conn| conn.send(resp) }


    if team=="admin"
      @admin = ws_conn
      case st
      when "prev", "next"
        @musicpos += (st=="prev" ? -1 : 1)
        @musicpos = [[0, @musicpos].max, @musiclist.length-1].min
        ans = {}; @rediness = {};
        msg = sprintf("src=%s", @musiclist[@musicpos]["ファイル名"])
        m = @musiclist[@musicpos]
        jsn = {url: m["ファイル名"], hint: m["ヒント"]}
        p JSON.generate(jsn)
        msg = sprintf("src=%s", JSON.generate(jsn))
        @stoptime = nil
      when "RESET"
        ans = {}; msg="RESET"
        @stoptime = nil
      when "PLAY", "STOP"		# /STOP: ([0-9.]+)/
        if st=="STOP"
          @stoptime = jv['curtime']
          STDERR.printf("stoptime saved = %f\n", @stoptime)
        end
        maxdelay = clients.keys.collect{|x|clients[x]["delay"]}.max
        clients.keys.each{|c|
          d = maxdelay-clients[c]["delay"]
          c.send("#{st}: #{d} #{@stoptime||0}")
        }
        msg=""
      when "SABI"
        clm = @musiclist[@musicpos]["サビ秒数"]||10
        clients.keys.each{|c|
          c.send("PLAY: 0 #{clm}")	# 仮に10秒とする 変えてね!
        }
        msg=""
        
      else
        msg = ans.keys.select{|x|x!="admin"}.join(", ")
      end
      #if false && /prev|next/ =~ st
      # STDERR.printf("Set pos @ %d -> %s\n", @musicpos, @musiclist[@musicpos])
      #  @rediness = {}
      #  clients.keys.each{|conn|
      #    conn.send(msg) # if conn!=ws_conn;
      #  }
      if msg>""
        clients.keys.each{|conn| conn.send(msg)}
      end
    end
    p ans
    resp = ans.keys.select{|x|x!="admin"}.sort_by{|k| ans[k].min}.join(", ")
    p ans.keys.select{|x|x!="admin"}.sort_by{|k| ans[k].min}
    case st
    when /PONG/i
      a = clients[ws_conn]
      a["pong"] = Time.now.to_f
      a["delay"] = a["pong"]-a["ping"]
      p clients.values.collect{|v| v['delay']}.join(", ")
    when /loading done/i
      @rediness[ws_conn] = true
      msg = "RESET"
      STDERR.printf("%d/%d\n", @rediness.keys.length, clients.keys.length)
      # clients.keys.each{|conn| conn.send("RESET")}
      @admin.send(sprintf("LOAD: %d/%d\n", @rediness.keys.length, clients.keys.length))
      if @rediness.keys.length == clients.keys.length then
        clients.keys.each {|conn|
          if conn != @admin
            STDERR.puts("Sending RESET to #{conn}")
            conn.send("RESET")
          end
        }
      end
    end
    if /PLAY|STOP|RESET|loading/ !~ st
      clients.keys.each{|conn| conn.send(resp);}
    end
  end
  ws_conn.onclose do
    clients.delete(ws_conn)
    @rediness
    # p "bye"+ws_conn.inspect
    printf("%d GUEST(s)\n", clients.keys.length)
  end
  EM::defer do
    puts "..captured!"
    loop do
      print("Hit Return to Reset client messages...")
      line = gets
      puts("Resetting")
      clients.keys.each{|conn| conn.send("Ready..") }
      ans = {};
    end
  end
end
