#!/usr/bin/env ruby
#--
# This file is part of Sonic Pi: http://sonic-pi.net
# Full project source: https://github.com/samaaron/sonic-pi
# License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md
#
# Copyright 2013, 2014, 2015, 2016 by Sam Aaron (http://sam.aaron.name).
# All rights reserved.
#
# Permission is granted for use, copying, modification, and
# distribution of modified versions of this work as long as this
# notice is included.
#++

require_relative "../core.rb"

require 'rubame'
require 'webrick'
require 'json'

require_relative "../sonicpi/lib/sonicpi/studio"
require_relative "../sonicpi/lib/sonicpi/spider"
require_relative "../sonicpi/lib/sonicpi/spiderapi"
require_relative "../sonicpi/lib/sonicpi/server"
require_relative "../sonicpi/lib/sonicpi/util"
require_relative "../sonicpi/lib/sonicpi/rcv_dispatch"

include SonicPi::Util

ws_out = Queue.new
web_server = nil

at_exit do
  puts "Exiting - shutting down web server..."
  web_server.shutdown if web_server
end

puts "starting server stuff"
# This is pretty klunky at the moment
# Find a way to hide it from clients...
user_methods = Module.new
name = "SonicPiSpiderUser1" # this should be autogenerated
klass = Object.const_set name, Class.new(SonicPi::Spider)
klass.send(:include, user_methods)
klass.send(:include, SonicPi::SpiderAPI)
klass.send(:include, SonicPi::Mods::Sound)
puts "starting sp"
$sp =  klass.new "localhost", 4556, ws_out, 5, user_methods
puts "finished starting sp"
$rd = SonicPi::RcvDispatch.new($sp, ws_out)
$clients = []


# Send stuff out from Sonic Pi jobs out to GUI
out_t = Thread.new do
  loop do
    begin
      message = ws_out.pop
      if debug_mode
        raise "message not a Hash!" unless message.is_a? Hash
      end
      message[:ts] = Time.now.strftime("%H:%M:%S")

      if debug_mode
        puts "sending:"
        puts "#{JSON.fast_generate(message)}"
        puts "---"
      end
      $clients.each{|c| c.send(JSON.fast_generate(message))}
    rescue Exception => e
      puts e.message
      puts e.backtrace.inspect
    end
  end
end

# Receive events from the GUI to Sonic Pi (potentially creating new jobs)

# ws_server = Rubame::Server.new("0.0.0.0", 8001)
ws_server = Rubame::Server.new("localhost", 8001)

in_t = Thread.new do
  while true
    ws_server.run do |client|
      client.onopen do
        client.send(JSON.fast_generate({:type => :message, :val => "Connection initiated..."}))
        $clients << client
        puts "New Websocket Client: \n#{client.frame} \n #{client.socket} \n"

      end
      client.onmessage do |msg|
        begin
          parsed = JSON.parse(msg)
          $rd.dispatch parsed
        rescue Exception => e
          puts "Unable to parse: #{msg}"
          puts "Reason: #{e}"
          puts "Backtrace: #{e.backtrace}"
        end
      end
      client.onclose do
        $clients.delete client
        warn("Connection closed...")
      end
    end
  end
end

# $web_server = WEBrick::HTTPServer.new :Port => 8000, :BindAddress => "0.0.0.0" , :DocumentRoot => html_public_path
$web_server = WEBrick::HTTPServer.new :Port => 8000, :BindAddress => "localhost" , :DocumentRoot => html_public_path

web_t = Thread.new { $web_server.start}



out_t.join
in_t.join
web_t.join
