
/*
 * 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 ../common/Weinre
requireClass ../common/IDLTools

//-----------------------------------------------------------------------------
class InspectorFrontendHostImpl
        
    this._getPlatformAndPort()

//-----------------------------------------------------------------------------
method loaded
    // WebInspector.Settings.initialize()
    
//-----------------------------------------------------------------------------
method closeWindow
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method disconnectFromBackend
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method bringToFront
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method inspectedURLChanged(newURL)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method requestAttachWindow
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method requestDetachWindow
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method setAttachedWindowHeight(height)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method moveWindowBy(x, y)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method setExtensionAPI(script)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method localizedStringsURL
    return "nls/English.lproj/localizedStrings.js";

//-----------------------------------------------------------------------------
method hiddenPanels
    return "audits,profiles,resources,timeline,network"
//    return "audits,profiles,resources,scripts,timeline,network"

//-----------------------------------------------------------------------------
method copyText(text)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method platform
    return "weinre"

//-----------------------------------------------------------------------------
method port
    return "weinre"

//-----------------------------------------------------------------------------
method showContextMenu(event, items)
    Weinre.notImplemented(arguments.callee.signature)

//-----------------------------------------------------------------------------
method sendMessageToBackend(message)
    var object = JSON.parse(message)
    if (object[0] == "setInjectedScriptSource") {
        object[1] = "<long script elided>"
    }
    console.log(arguments.callee.signature + "(" + JSON.stringify(object,null,4) + ")")

//-----------------------------------------------------------------------------
method _getPlatformAndPort
    this._platform       = "weinre"
    this._platformFlavor = "weinre"
    this._port           = "weinre"
        
    if (true) return
    
    // get values from user agent
    var uas = navigator.userAgent
    if      (uas.match(/mac os x/i))  this._platform = "mac"
    else if (uas.match(/macintosh/i)) this._platform = "mac"
    else if (uas.match(/linux/i))     this._platform = "linux"
    else if (uas.match(/windows/i))   this._platform = "windows"
        
    // get values from hash value
    var url = window.location.href
    
    var splits = url.split("#",2)
    if (splits.length > 1) {
        var properties = splits[1]
        properties = properties.split("&")
        
        properties.forEach(function(property) {
            var pieces = property.split("=")
            if (pieces.length > 1) {
                var key = pieces[0]
                var val = pieces[1]
                
                if      (key == "platform")       this._platform       = val
                else if (key == "platformFlavor") this._platformFlavor = val
                else if (key == "port")           this._port           = val
            }
        })
        
    }
