#! /usr/bin/env ruby

require 'eventmachine'
require 'rack'
require 'thin'
require 'orocos'
require 'rack/static'
require 'sprockets'
require 'rock/webapp/tasks'
require 'optparse'

thin_host = '0.0.0.0'
thin_port = 9292

name_server_hosts=[]

cors_hosts = []
syskit = false
config_dir = ENV['ROCK_WEBAPP']
src_dir = File.expand_path(
    Pathname.new(File.dirname(__FILE__)).parent)

options = OptionParser.new do |opt|
    opt.on('--host host', String, 'the host of the name server that should be contacted (default to localhost)') do |host|
        name_server_hosts << host
    end
    opt.on('--bind host', String, 'the host the server should bind to (default to 0.0.0.0)') do |host|
        thin_host = host
    end
    opt.on('--port port', Integer, "the server's port (default to #{thin_port})") do |port|
        thin_port = port
    end
    opt.on('--enable-cors hosts', Array, "enables Cross-Origin Resource Sharing for sites loaded from the parameter may include localhost host:port, file://. Also multiple values seperated by ','") do |host|
        cors_hosts << host
    end
    opt.on('--enable-syskit',"load syskit support") do
        syskit=true
    end
    opt.on('--config-dir dir', String, 'directory where the configuration can be found') do |dir|
        config_dir = dir
    end
end
options.parse ARGV

# set up websocket handling
Faye::WebSocket.load_adapter('thin')
thin = Rack::Handler.get('thin')
EM.next_tick { Rock::WebApp::Tasks.install_event_loop }

if syskit
    #includes roby app that changes a log path, must be included before Orocos.initialize
    require 'rock/webapp/syskit'
end

#if no --host option is given: add the default host 'localhost'
if name_server_hosts.empty?
    name_server_hosts << 'localhost'
end

#use the first entry as default name server and remove it from list
Orocos::CORBA.name_service.ip = name_server_hosts.first
name_server_hosts.shift

#add the remaining additional name servers
name_server_hosts.each do |host_address|
    Orocos.name_service << Orocos::CORBA::NameService.new(host_address)
end
Orocos.initialize

app = Rack::Builder.new do
    # create a sprockets environment, and allow plugins to add paths
    # to it
    environment = Sprockets::Environment.new
    environment.append_path File.join( src_dir, 'assets', 'js')
    environment.append_path File.join( src_dir, 'assets', 'css')

    # load the ruby files in the plugin dir, and call instance_eval
    # in this way, the plugins can register mappings using the same syntax
    if config_dir 
        plugin_dir = File.expand_path( File.join( config_dir, "plugins" ) )
        if File.directory? plugin_dir
            # for that, add the directory to the ruby load path
            $:.unshift( plugin_dir ) unless $:.include? plugin_dir 
            Dir.glob File.join( plugin_dir, "*.rb" ) do |file|
                instance_eval File.read( file )
            end
        end
    end

    #map asset handler, which will process the local js files and serve
    #the client side js code. For now, this will always use sprockets
    #to serve the assets. In a production system the pipeline would be 
    #to use a rake task to compile to a static directory, and serve 
    #statically
    map '/assets' do
        run environment
    end
    
    #map the apis
    map '/api/tasks' do
        if !cors_hosts.empty?
            require 'rack/cors'
            use Rack::Cors do
                allow do
                    origins(*cors_hosts)
                    resource '*', headers: :any, methods: [:get, :post]
                end
            end
        end
        run Rock::WebApp::Tasks::Root
    end
    
    if syskit
        map '/api/syskit' do
            if !cors_hosts.empty?
                require 'rack/cors'
                use Rack::Cors do
                    allow do
                        origins(*cors_hosts)
                        resource '*', headers: :any, methods: [:get, :post]
                    end
                end
            end
            run Rock::WebApp::Syskit::Root
        end
    end
end
thin.run(app, Host: thin_host, Port: thin_port)

