const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
var strings = Services.strings;
var proSrc = "chrome://TrayHotKey/locale/libTHK.properties";
var bundle = strings.createBundle(proSrc);
var THK = {
    tray: 0
}
var AppObserver = {
    get os() {
        return Cc["@mozilla.org/observer-service;1"]
                  .getService(Ci.nsIObserverService);
    },
    observe: function (aSubject, aTopic, aData) {
        if (aTopic == "quit-application") {
            postMessage({"name": "Quit"});
            this.os.removeObserver(this, "quit-application");
        }
    },
    register: function () {
        this.os.addObserver(this, "quit-application", false);
    }
}
AppObserver.register();

THK.wv = (function () {
    var wrk = Cc["@mozilla.org/windows-registry-key;1"]
                  .createInstance(Ci.nsIWindowsRegKey);
    wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
             "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
             wrk.ACCESS_READ
    );
    var wv = wrk.readStringValue("CurrentVersion");
    wrk.close();
    return wv;
})();
// 测试图标文件是否存在，存在则返回其绝对路径
// 其文件须放在 Firefox 的配置目录下
THK.exists = function (ico) {
    if (ico == "") return null;
    let dirService = Cc["@mozilla.org/file/directory_service;1"].
                        getService(Ci.nsIProperties);
    let profile = dirService.get("ProfD", Ci.nsIFile);
    profile.append(ico);
    return (profile.exists() && profile.isFile()) ? profile.path : "\0";
}

/* -*- 获取扩展的物理绝对路径 -*- */
THK.getExPath = function () {
    let _ID_ = "\\extensions\\TrayHotKey@zbinlin.org";
    let dirService = Cc["@mozilla.org/file/directory_service;1"]
                     .getService(Ci.nsIProperties);
    let profile = dirService.get("ProfD", Ci.nsIFile);
    return profile.path + _ID_;
}

THK.observe = function (aSubject, aTopic, aData) {
    if (aTopic != "nsPref:changed") return;
    aSubject.QueryInterface(Ci.nsIPrefBranch)
            .QueryInterface(Ci.nsIPrefBranch2);
    switch (aSubject.getPrefType(aData)) {
        case aSubject.PREF_BOOL :
            postMessage({
                'name': aData,
                'value' : aSubject.getBoolPref(aData)
            });
            break;
        case aSubject.PREF_INT :
            postMessage({
                'name': aData,
                'value' : aSubject.getIntPref(aData)
            });
            break;
        case aSubject.PREF_STRING :
            postMessage({
                'name': aData,
                'value' : aSubject.getCharPref(aData)
            });
            break;
    }
}
THK.register = function () {
    let aPrefs  = Services.prefs;
    this.branch = aPrefs.getBranch("extensions.TrayHotKey.");
    this.branch.QueryInterface(Ci.nsIPrefBranch2);
    this.branch.addObserver("", this, false);

    try {
        let ico = this.branch.getComplexValue("TrayIconPath",
                    Ci.nsIPrefLocalizedString).data;
        this.icoPath = this.exists(ico);
    } catch (err) {
        this.icoPath = '\0';
    }
    this.hotKeyChecked = this.branch.getBoolPref("setHotKey_bool");
    this.keyCode       = this.branch.getIntPref("KeyCode");
    let alawysShowTray = this.branch.getBoolPref("alawysShowTray_bool");
    let minimizeToTray = this.branch.getBoolPref("minimizeToTray_bool");
    let closeToTray    = this.branch.getBoolPref("closeToTray_bool");
    let foreground     = this.branch.getBoolPref("foreground");
    let windowTop      = this.branch.getBoolPref("pinWindowTop");
    let singleWin      = this.branch.getBoolPref("singleWinMode");
    let minimizeToFm   = this.branch.getBoolPref("minimizeToFm_bool");
    this.tray |= alawysShowTray ? 0x01 : 0x00;
    this.tray |= minimizeToTray ? 0x02 :0x00;
    this.tray |= closeToTray ? 0x04 : 0x00;
    this.tray |= foreground ? 0x08 : 0x00;
    this.tray |= windowTop ? 0x10 : 0x00;
    this.tray |= singleWin ? 0x20 : 0x00;
    this.tray |= minimizeToFm ? 0x40 : 0x00;
    let quit, show, hide, trayToolTip, otherWindows, pinWindowTop;
    quit = bundle.GetStringFromName("quit") ? bundle.GetStringFromName("quit")
                                            : "quit";
    show = bundle.GetStringFromName("show") ? bundle.GetStringFromName("show")
                                            : "show";
    hide = bundle.GetStringFromName("hide") ? bundle.GetStringFromName("hide")
                                            : "hide";
    trayToolTip = bundle.GetStringFromName("trayToolTip") ?
                    bundle.GetStringFromName("trayToolTip") : "FIREFOX";
    try {
        otherWindows = this.branch.getComplexValue("otherWindows",
                            Ci.nsIPrefLocalizedString).data;
    } catch (err) {
        otherWindows = '\0';
    }
    pinWindowTop = bundle.GetStringFromName("pinTop") ?
                        bundle.GetStringFromName("pinTop") : "pinWindowTop";
    this.trayStr = [quit, show, hide, trayToolTip, otherWindows, pinWindowTop];
}
THK.register();


/*
var workerFactory = Cc["@mozilla.org/threads/workerfactory;1"]
                    .getService(Ci.nsIWorkerFactory);
const Worker = workerFactory.newChromeWorker("resource://THKLibs/worker.js");
*/
var Worker = {};
Cu.import("resource://THKLibs/worker.js", Worker);
var postMessage = function (aMsg) {
    return Worker.onmessage(aMsg);
}
var onmessage = function (aMsg) {
    let aPrefs  = Services.prefs;
    let branch = aPrefs.getBranch("extensions.TrayHotKey.");
    let data = aMsg;
    switch (data.name) {
        case "InitEnd" :
            postMessage({
                "name"          : "TrayHotKey",
                "icoPath"       : THK.icoPath,
                "trayStr"       : THK.trayStr,
                "trayChecked"   : THK.tray,

                "hotKeyChecked" : THK.hotKeyChecked,
                "keyCode"       : THK.keyCode
            });
            break;
        case "InitWINEND" :
            if (THK.wv >= 6.0) {
                postMessage({
                    "name"           : "InitOpacity",
                    "opacityChecked" : branch.getBoolPref("setOpacity_bool"),
                    "opacityValue"   : branch.getIntPref("opacity_int"),
                    "transValue"     : branch.getIntPref("trans_int"),
                    "transChecked"   : branch.getBoolPref("setTrans_bool"),
                    "transKC"        : branch.getIntPref("TransKeyCode")
                });
            }
            break;
        case "HotKeyStatus" :
            branch.setBoolPref("HotKeyStatus", data.value);
            break;
        case "TransStatus" :
            branch.setBoolPref("TransStatus", data.value);
            break;
    }
}
var that = this;
/* -*- 初始化 dll -*- */
postMessage({
        "name": "Init",
        "that": that,
        "value": THK.getExPath() + "\\components\\libTHK.dll"
});


function TrayHotKey() {
    this.wrappedJSObject = this;
}

TrayHotKey.prototype = {
    classDescription: "TrayHotKey XPCOM",
    classID: Components.ID("{5CAABB46-C1F9-4946-BC9F-6DFB4B656D3E}"),
    contractID: "@czcp.co.cc/TrayHotKey;1",

    /*
    _xpcom_factory: { ... },
    _xpcom_categories: [{
        category: "some-category",
        entry: "entry name",
        value: "...",
        service: true
    }],
    */

    QueryInterface: XPCOMUtils.generateQI(),

    initWIN: function () {
        postMessage({"name": "InitWIN"});
    },
    onWinTop: function (title) {
        if (!title) return false;
        return postMessage({"name": "WinTop", "value": title});
    }
};

var components = [TrayHotKey];
const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
