
/*
 * weinre is available under *either* the terms of the modified BSD license *or* the
 * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
 * 
 * Copyright (c) 2010, 2011 IBM Corporation
 */

requireClass ./Ex
requireClass ./Weinre
requireClass ./EventListeners

//-----------------------------------------------------------------------------
class WebSocketXhr(url)
    this.initialize(url)
    
//-----------------------------------------------------------------------------
init
    WebSocketXhr.CONNECTING = 0
    WebSocketXhr.OPEN       = 1
    WebSocketXhr.CLOSING    = 2
    WebSocketXhr.CLOSED     = 3

//-----------------------------------------------------------------------------
method initialize(url)
    this.readyState      = WebSocketXhr.CONNECTING 
    this._url            = url
    this._urlChannel     = null
    this._queuedSends    = []
    this._sendInProgress = true
    
    this._listeners = {
        open:    new EventListeners(),
        message: new EventListeners(),
        error:   new EventListeners(),
        close:   new EventListeners()
    }
    
    this._getChannel()

//-----------------------------------------------------------------------------
method _getChannel
    this._xhr(this._url, "POST", "", this._handleXhrResponseGetChannel)

//-----------------------------------------------------------------------------
method _handleXhrResponseGetChannel(xhr)
    if (xhr.status != 200) return this._handleXhrResponseError(xhr)

    try {
        var object = JSON.parse(xhr.responseText)
    }
    catch (e) {
        this._fireEventListeners("error", {message: "non-JSON response from channel open request"})
        this.close()
        return
    }
    
    if (!object.channel) {
        this._fireEventListeners("error", {message: "channel open request did not include a channel"})
        this.close()
        return
    }
    
    Weinre.connectorId = object.channel
    
    this._urlChannel = this._url + "/" + object.channel
    this.readyState = WebSocketXhr.OPEN

    this._fireEventListeners("open", { message: "open" })
    
    this._sendInProgress = false
    this._sendQueued()
    
    this._readLoop()

//-----------------------------------------------------------------------------
method _readLoop
    if (this.readyState == WebSocketXhr.CLOSED) return
    if (this.readyState == WebSocketXhr.CLOSING) return
    
    this._xhr(this._urlChannel, "GET", "", this._handleXhrResponseGet)

//-----------------------------------------------------------------------------
method _handleXhrResponseGet(xhr)
    var self = this
    
    if (xhr.status != 200) return this._handleXhrResponseError(xhr)

    try {
        var datum = JSON.parse(xhr.responseText)
    }
    catch (e) {
        this.readyState = WebSocketXhr.CLOSED
        
        this._fireEventListeners("error", {
            message: "non-JSON response from read request"
        })
        return
    }
    
    window.setTimeout(function() {self._readLoop()}, 0)

    datum.forEach(function(data) {
        self._fireEventListeners("message", {data: data})
    })

//-----------------------------------------------------------------------------
method send(data)
    if (typeof data != "string") throw new Ex(arguments, this.constructor.name + "." + this.caller)

    this._queuedSends.push(data)
    
    if (this._sendInProgress) return
    this._sendQueued();

//-----------------------------------------------------------------------------
method _sendQueued
    if (this._queuedSends.length == 0) return
    if (this.readyState == WebSocketXhr.CLOSED) return
    if (this.readyState == WebSocketXhr.CLOSING) return
    
    datum = JSON.stringify(this._queuedSends)
    this._queuedSends = []
    
    this._sendInProgress = true
    
    this._xhr(this._urlChannel, "POST", datum, this._handleXhrResponseSend)

//-----------------------------------------------------------------------------
method _handleXhrResponseSend(xhr)
    var httpSocket = this
    
    if (xhr.status != 200) return this._handleXhrResponseError(xhr)
    
    this._sendInProgress = false
    window.setTimeout(function() {httpSocket._sendQueued()}, 0)

//-----------------------------------------------------------------------------
method close
    this._sendInProgress = true
    this.readyState = WebSocketXhr.CLOSING
    this._fireEventListeners("close", {
        message: "closing",
        wasClean: true
    })
    this.readyState = WebSocketXhr.CLOSED

//-----------------------------------------------------------------------------
method addEventListener(type, listener, useCapture)
    this._getListeners(type).add(listener, useCapture)

//-----------------------------------------------------------------------------
method removeEventListener(type, listener, useCapture)
    this._getListeners(type).remove(listener, useCapture)

//-----------------------------------------------------------------------------
method _fireEventListeners(type, event)
    if (this.readyState == WebSocketXhr.CLOSED) return
    
    event.target = this
    this._getListeners(type).fire(event)

//-----------------------------------------------------------------------------
method _getListeners(type)
    var listeners = this._listeners[type]
    if (null == listeners) throw new Ex(arguments, "invalid event listener type: '" + type + "'")
    
    return listeners

//-----------------------------------------------------------------------------
method _handleXhrResponseError(xhr)
    if (xhr.status == 404) {
        this.close()
        return
    }
    
    this._fireEventListeners("error", {
        target: this,
        status: xhr.status,
        message: "error from XHR invocation: " + xhr.statusText
    })
    
    console.log("error from XHR invocation: " + xhr.status + ": " + xhr.statusText)

//-----------------------------------------------------------------------------
method _xhr(url, method, data, handler)
    if (null == handler) throw new Ex(arguments, "handler must not be null")
    
    var xhr = new XMLHttpRequest()
    
    xhr.httpSocket         = this
    xhr.httpSocketHandler  = handler
    xhr.onreadystatechange = _xhrEventHandler
    
    xhr.open(method, url, true)
    xhr.setRequestHeader("Content-Type", "text/plain")
    xhr.send(data)

//-----------------------------------------------------------------------------
function _xhrEventHandler(event)
    var xhr = event.target
    if (xhr.readyState != 4) return
    
    xhr.httpSocketHandler.call(xhr.httpSocket, xhr) 
