(function () {
    const Cu = Components.utils;
    
    var jsm = { };
    if (typeof XPCOMUtils == "undefined") {    
        Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    }
    
    XPCOMUtils.defineLazyGetter(jsm, "utils", function() {
        let obj = { };
        Cu["import"]("resource://livemargins/utils.jsm", obj);
        return obj.utils;
    });
    
    XPCOMUtils.defineLazyGetter(jsm, "AppCenter", function() {
        let obj = { };
        Cu["import"]("resource://livemargins/appcenter.jsm", obj);
        return obj.AppCenter;
    });
    
    XPCOMUtils.defineLazyGetter(jsm, "logger", function() {
        return new jsm.utils.logger("LM4.FlashExtractor");
    });
    
    var ns = MOA.ns('LM4.flashExtractor');
    
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (context) {
            var __method = this, args = Array.prototype.slice.call(arguments, 1);
            return function() {
                return __method.apply(context, args.concat(Array.prototype.slice.call(arguments, 0)));
            }
        };
    }
    
    var minWidth = 160;
    var minHeight = 90;
    
    function flashVideoPlayer(win) {
        this.win = win;
        this.control = null;
        this.targetEmbed = null;
        this.initialize();
    }
    
    flashVideoPlayer.prototype = {
        initialize: function() {
            this.addEventListeners();
        },
        
        addEventListeners: function() {
            var self = this;
            
            function _onmouseover(evt) {
                if ((evt.originalTarget instanceof HTMLEmbedElement || evt.originalTarget instanceof HTMLObjectElement) &&
                    evt.originalTarget.offsetWidth >= minWidth && 
                    evt.originalTarget.offsetHeight >= minHeight) {
                    self.showControl(evt);
                }
            }
            
            function _onmouseout(evt) {
                if ((evt.originalTarget instanceof HTMLEmbedElement || evt.originalTarget instanceof HTMLObjectElement)) {
                    self.hideControl(evt);
                }
            }
            
            this.win.document.addEventListener("mouseover", _onmouseover, false);
            this.win.document.addEventListener("mouseout", _onmouseout, false);
            
            this.win.addEventListener("unload", function() {
                self.win.document.removeEventListener("mouseover", _onmouseover, false);
                self.win.document.removeEventListener("mouseout", _onmouseover, false);
                if (self.control && self.control.parentNode) {
                    self.win.document.body.removeChild(self.control);
                }
                this.win = null;
                this.control = null;
                this.targetEmbed = null;
                jsm.logger.trace("destruct flash extractor.");
            }, false);
        },
        
        _createControl: function() {
            var doc = this.win.document;
            if (null == this.control) {
                this.control = doc.createElement('div');
                
                var self = this;
                this.control.addEventListener("mouseover", function (evt) {
                    self.showControl(evt);
                }, false);
                
                this.control.addEventListener("mouseout", function (evt) {
                    self.hideControl(evt);
                }, false);
                
                this.control.style.position = "absolute";
                this.control.style.display = "none";
                this.control.style.zIndex = 9999;
                
                this.control.innerHTML = '<img width="77" height="5" ' +
                        '     src="chrome://livemargins/skin/monitor-background-horizontal.png" ' +
                        '     style="position: absolute;left:-77px;top:-5px"/>' +
                        '<img src="chrome://livemargins/skin/monitor-background-vertical.png" ' +
                        '     style="position: absolute;left:0;top:-5px;"/>' +
                        '<img id="monitor-play-button" src="chrome://livemargins/skin/monitor-play-button.png" ' +
                        '     onmouseover="this.style.opacity=1" onmouseout="this.style.opacity=0.5" ' +
                        '     style="position: absolute;left:1px;top:0;opacity:0.5;cursor:pointer"/>';
                
                
                this.control.childNodes[2].addEventListener('click', function(event) {
                    self.playVideo(event);
                }, false);
            }
            // append control element dynamically.
            doc.body.appendChild(this.control);
        },
        
        showControl: function(evt) {
            this._createControl();
            
            jsm.logger.trace('Show flash extractor button.');
            
            var target = evt.originalTarget;
            var doc = this.win.document;
            
            if ((target.tagName.toLowerCase() == 'embed' || target.tagName.toLowerCase() == 'object')) {
                this.targetEmbed = target != this.targetEmbed ? target : this.targetEmbed;
            }
            
            var pos = jsm.utils.getRectTRBLWH(this.targetEmbed, this.win);
            var left = doc.defaultView.scrollX + pos.right;
            var top = doc.defaultView.scrollY + pos.top;
            this.control.style.top = top + "px";
            this.control.style.left = left + "px";
            this.control.style.display = "block";
            this.control.setAttribute("hiding", false);
            
            this.showAndHideControl();
        },
        
        hideControl: function(evt) {
            if (!this.control) {
                return;
            }
            this.control.setAttribute("hiding", true);
            this.showAndHideControl();
        },
        
        showAndHideControl: function() {
            var self = this;
            var hiding = this.control.getAttribute("hiding");
            if (hiding == "true") {
                if (this.control.style.opacity > 0) {
                    if (this.control.style.opacity == "") {
                        this.control.style.opacity = 1;
                    }
                    this.control.style.opacity = parseFloat(this.control.style.opacity) - 0.1;
                    
                    window.setTimeout(function() {
                        self.showAndHideControl();
                    }, 50);
                } else {
                    if (this.control.parentNode) {
                        self.win.document.body.removeChild(this.control);
                    }
                    this.control.display = "none";
                }
            } else {
                if (this.control.style.opacity < 1) {
                    if (this.control.style.opacity == "") {
                        this.control.style.opacity = 0;
                    } else {
                        this.control.style.opacity = parseFloat(this.control.style.opacity) + 0.1;
                    }
                    
                    window.setTimeout(function() {
                        self.showAndHideControl();
                    }, 50);
                }
            }    
        },
        
        playVideo: function(event) {
            var doc = this.targetEmbed.ownerDocument;
            var pos = jsm.utils.getRectTRBLWH(this.targetEmbed, getBrowser().selectedBrowser.contentWindow);
            var fullZoom = gBrowser.selectedBrowser.markupDocumentViewer.fullZoom;
            
            var screenX = pos.left * fullZoom + window.screenX + 1;
            
            // 鼠标屏幕位置 - 鼠标相对于元素的位置 * 放大倍数 - 播放窗口的标题栏高度
            var screenY = event.screenY - (event.clientY - pos.top) * fullZoom - 30;
            
            var tagName = this.targetEmbed.tagName;
            var elementIndex = -1;
            if (tagName){
                var elems = doc.getElementsByTagName(tagName);
                for (i = 0; i < elems.length; i++){
                    if (elems[i] == this.targetEmbed){
                        elementIndex = i;
                    }
                }
            }
            jsm.logger.trace(tagName + " " + elementIndex);
            
            if (tagName && elementIndex != -1){
                if (this.targetEmbed.clientWidth > minWidth && this.targetEmbed.clientHeight > minHeight) {
                    var args = {
                        name     : doc.title,
                        location : doc.URL,
                        docX     : pos.left / fullZoom + doc.defaultView.scrollX,
                        docY     : pos.top / fullZoom + doc.defaultView.scrollY,
                        screenX  : screenX,
                        screenY  : screenY,
                        width    : this.targetEmbed.clientWidth,
                        height   : this.targetEmbed.clientHeight,
                        browserWidth  : window.content.document.documentElement.clientWidth,
                        browserHeight : window.content.document.documentElement.clientHeight,
                        zoom: fullZoom,
                        tagName: tagName, 
                        elementIndex: elementIndex,
                        elementWidth: this.targetEmbed.clientWidth,
                        elementHeight: this.targetEmbed.clientHeight
                    };
                    var appUID = jsm.AppCenter.addVideoPlayer(args);
                    jsm.logger.trace(appUID + ' has been created, open it.');
                    jsm.AppCenter.openApp(appUID);
                } else {
                    var control = doc.getElementById("livemargins_control");
                    control.setAttribute("hiding", true);
                    control.style.display = "none";
                    control.style.opacity = 0;
                }
            } else {
                var args = {
                    name     : doc.title,
                    location : doc.URL,
                    docX     : pos.left / fullZoom + doc.defaultView.scrollX,
                    docY     : pos.top / fullZoom + doc.defaultView.scrollY,
                    screenX  : screenX,
                    screenY  : screenY,
                    width    : this.targetEmbed.clientWidth,
                    height   : this.targetEmbed.clientHeight,
                    browserWidth  : window.content.document.documentElement.clientWidth,
                    browserHeight : window.content.document.documentElement.clientHeight,
                    zoom: fullZoom
                };
                var appUID = jsm.AppCenter.addWebClipping(args);    
                jsm.logger.trace(appUID + ' has been created, open it.');
                jsm.AppCenter.openApp(appUID);
            }
        }
    }
        
    function init() {
        document.getElementById('appcontent').addEventListener('DOMContentLoaded', function(evt) {
            if (!evt.originalTarget instanceof HTMLDocument) {
                return;
            }
            var view = evt.originalTarget.defaultView;
            jsm.logger.trace('Inject flash extractor button.');
            new flashVideoPlayer(view);
        }, false);
    }
    
    window.addEventListener('load', function() {
        window.setTimeout(init, 1000);
        window.removeEventListener("load", arguments.callee, false);
    }, false);
})();