/* 
 Copyright 2010 Xmarks Inc.

 foxmarks-uitools.js: Various and sundry UI functions. 

 */

var Cc = Components.classes;
var Ci = Components.interfaces;
var CCon = Components.Constructor;

(function() {
var xm = Xmarks;

function MigratePW() {
    // Migrate password if necessary.
    Xmarks.LogWrite("Attempting PW Migration...");
    var host = (Xmarks.gSettings.securityLevel == -1 
        ? "http://" : "https://") + Xmarks.gSettings.acctMgrHost;
    var password = Xmarks.gSettings.passwordNoPrompt;
    var mgr = this.Cc["@mozilla.org/login-manager;1"]
        .getService(this.Ci.nsILoginManager);
    var li = Cc[ "@mozilla.org/login-manager/loginInfo;1"].
        createInstance(Ci.nsILoginInfo);
    li.init(host, host, null, Xmarks.gSettings.username, password, 
        "username", "password");

    var logins = mgr.findLogins({}, host, host, null).
        filter(function(l) l.matches(li, true));
    if (logins.length) {
        Xmarks.LogWrite("Clearing existing login...");
        try {
            mgr.removeLogin(logins[0]);
            Xmarks.LogWrite("Done.");
        } catch(e) {
            Xmarks.LogWrite("Failed.");
        }
    }

    Xmarks.LogWrite("Adding new login...");
    try {
        mgr.addLogin(li);
        Xmarks.LogWrite("Done.");
    } catch(e) {
        Xmarks.LogWrite("Failed (probably already exists).");
    }

    // Now remove the old password.
    var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
        Ci.nsILoginInfo, "init");
    var newli = new nsli(Xmarks.gSettings.host, null, 
        Xmarks.SYNC_REALM, Xmarks.gSettings.username, 
        password, "", "");
    var oldli = new nsli(Xmarks.gSettings.host, null, 
        Xmarks.FOXMARKS_SYNC_REALM, Xmarks.gSettings.username, 
        password, "", "");

    Xmarks.LogWrite("Removing old Xmarks password...");
    try {
        mgr.removeLogin(newli);
        Xmarks.LogWrite("Done.");
    } catch(e) {
        Xmarks.LogWrite("Failed.")
    }

    Xmarks.LogWrite("Removing old Foxmarks password...");
    try {
        mgr.removeLogin(oldli);
        Xmarks.LogWrite("Done.");
    } catch(e) {
        Xmarks.LogWrite("Failed.")
    }
    Xmarks.LogWrite("PW Migration complete.");
}

xm.DoModalAuth = function(auto, reauth) {
    if (Xmarks.gSettings.useOwnServer)
        return 403;

    var express = !!(auto && Xmarks.gSettings.rememberPassword && 
        !Xmarks.gSettings.auth && Xmarks.gSettings.haveSynced &&
        Xmarks.gSettings.passwordNoPrompt);

    if (Xmarks.gSettings.passwordNoPrompt && Xmarks.gSettings.username) {
        try {
            MigratePW();
        } catch(e) {
            Xmarks.LogWrite("pw migration failed: " + e.toSource());
        }
    }

    var args = { 
        manual: !auto, 
        reauth: reauth, 
        express: express,
        newuser: !Xmarks.gSettings.haveSynced && !Xmarks.gSettings.auth
    };

    Xmarks.LogWrite("Starting modal auth(" + auto + ", " + reauth + ")");

    xm.ModalDialog(function() xm.OpenWindowByType("foxmarks:login", 
        "chrome://foxmarks/content/foxmarks-login.xul",
        "centerscreen,modal=yes,close=no", args));
    if (auto && args.status) {
        Xmarks.gSettings.suspended = true;
    }
    Xmarks.LogWrite("Finished modal auth with result " + args.status);
    return args.status;
}


xm.ModalDialog = function(func) {
    var fms = Xmarks.fms;
    if (fms.getState() == "working") {
        var os = Cc["@mozilla.org/observer-service;1"]
            .getService(Ci.nsIObserverService);
        os.notifyObservers(null, "foxmarks-statechange", "ready");
        var rv = func();
        os.notifyObservers(null, "foxmarks-statechange", "working");
        return rv;
    }
    return func();
}

xm.OpenWindowByType = function(inType, uri, features, args) {
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].
        getService(Ci.nsIWindowMediator);
    var topWindow = wm.getMostRecentWindow(inType);

    if (topWindow) {
        topWindow.focus();
    } else {
        topWindow = wm.getMostRecentWindow(null);
        var win = topWindow.openDialog(uri, "_blank", features || "chrome",
            args);
    }
};

xm.OpenInNewTabAuth = function(url, focus, auth){
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].
        getService(Ci.nsIWindowMediator);
    var topWindow = wm.getMostRecentWindow('navigator:browser');
    if (topWindow) {
        var content = topWindow.document.getElementById('content');
        if(auth !== undefined){
            var pd = Cc["@mozilla.org/network/mime-input-stream;1"].
                           createInstance(Ci.nsIMIMEInputStream);
            pd.addHeader("Authorization", "XMAuth "+ auth);
            pd.addHeader("X-Xmarks-Auth", auth);

            content.selectedTab =
                content.addTab(url, null,null , pd);
        } else {
            content.selectedTab =
                content.addTab(url);
        }
        if (focus) {
            topWindow.focus();
        }
    }
};

xm.OpenInNewTab = function(url, focus, postData) {
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].
        getService(Ci.nsIWindowMediator);
    var topWindow = wm.getMostRecentWindow('navigator:browser');
    if (topWindow) {
        var content = topWindow.document.getElementById('content');
        if(postData !== undefined){
            var stringStream = Cc["@mozilla.org/io/string-input-stream;1"].
                createInstance(Ci.nsIStringInputStream);
            var txt = postData.toJSONString();
            if ("data" in stringStream) // Gecko 1.9 or newer
                    stringStream.data = txt;
            else // 1.8 or older
                stringStream.setData(txt, txt.length);
                               
            var pd = Cc["@mozilla.org/network/mime-input-stream;1"].
                           createInstance(Ci.nsIMIMEInputStream);
            pd.addHeader("Content-Type", "application/json");
            pd.addContentLength = true;
            pd.setData(stringStream);

            content.selectedTab =
                content.addTab(url, null,null , pd);
        } else {
            content.selectedTab =
                content.addTab(url);
        }
        if (focus) {
            topWindow.focus();
        }
    }
};

const SCROLL_X = "xmarksScrollX";
const SCROLL_Y = "xmarksScrollY";

function ScrollTo(tab, x, y) {
    if (!x && !y) return;

    var browser = tab.linkedBrowser;
    browser[SCROLL_X] = x || 0;
    browser[SCROLL_Y] = y || 0;
    browser.addEventListener("load", ScrollToHandler, true, true);
}

function ScrollToHandler(event) {
    // Wait for the top frame to be loaded completely.
    if (!event || !event.originalTarget || !event.originalTarget.defaultView || 
        event.originalTarget.defaultView != event.originalTarget.defaultView.top) {
        return;
    }
    
    this.removeEventListener("load", ScrollToHandler, true, true);
    var content = event.originalTarget.defaultView;
    content.scrollTo(this[SCROLL_X], this[SCROLL_Y]);
    delete this[SCROLL_X];
    delete this[SCROLL_Y];
}

function OpenTabsInWindow(win, tabs) {
    tabs.forEach(function(t) {
        ScrollTo(win.gBrowser.addTab(t.url), t.scrollX, t.scrollY);
    });
}

xm.OpenTabs = function(tabs, newWindow, callback) {
    var w;
    var topWindow;

    if (!newWindow) {
        var wm = Cc['@mozilla.org/appshell/window-mediator;1'].
            getService(Ci.nsIWindowMediator);
        topWindow = wm.getMostRecentWindow('navigator:browser');
    }

    if (newWindow || !topWindow) {
        w = openDialog("chrome://browser/content/browser.xul", "_blank",
            "chrome,all,dialog=no", tabs[0].url);
        w.addEventListener("load", function() {
            w.setTimeout(function() {
                ScrollTo(w.gBrowser.mTabs[0], tabs[0].scrollX, tabs[0].scrollY);
                OpenTabsInWindow(w, tabs.slice(1));
                if (callback) callback();
            }, 0);
        }, false);
        return w;
    } else {
        OpenTabsInWindow(topWindow, tabs);
        if (callback) callback;
        return topWindow;
    }
}    


xm.OpenInNewWindow = function(url, callback) {
    if (typeof(url) == "object") {
        var w = openDialog("chrome://browser/content/browser.xul", "_blank",
            "chrome,all,dialog=no", url[0]);
        w.addEventListener("load", function() {
            var otherurls = url.slice(1);
            otherurls.forEach(function(u) { if (u) w.gBrowser.addTab(u); });
            if (callback) callback();
        }, false);
        return w;
    } else {
        return openDialog("chrome://browser/content/browser.xul", "_blank",
            "chrome,all,dialog=no", url);
    }
};

xm.OpenFoxmarksSettingsDialog = function(pane) {
    xm.OpenWindowByType("foxmarks:settings",
        "chrome://foxmarks/content/foxmarks-dialog.xul", 
        "chrome,toolbar,centerscreen",
        [pane || "foxmarks-mainpane"]);
};

xm.MyFoxmarks = function() {
    if(xm.gSettings.securityLevel == 1){
        xm.OpenInNewTab("https://my.xmarks.com/", true);
    } else {
        xm.OpenInNewTab("http://my.xmarks.com/", true);
    }
};

xm.OpenTabsPanel = function() {
    Xmarks.OpenWindowByType("xmarks:opentabs",
        "chrome://foxmarks/content/tabs.xul", 
        "chrome,toolbar,centerscreen,alwaysRaised=yes,resizable");
}

xm.OpenWizard = function(manual) {
    var s = Xmarks.DoModalAuth(manual);
    if (s) return s;

    xm.OpenWindowByType("foxmarks:setup",
        "chrome://foxmarks/content/foxmarks-setup.xul",
        "chrome,centerscreen,dialog=no", manual);
    return 0;
};

xm.OnWizardCancel = function() {
    var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
        .getService(Components.interfaces.nsIPromptService);

    var checkResult = {};
    checkResult.value = xm.gSettings.wizardSuppress;
    var sb = xm.Bundle();

    var ret = ps.confirmCheck(window, sb.GetStringFromName("title.cancelsetup"),
            sb.GetStringFromName("msg.cancelsetup"),
            sb.GetStringFromName("msg.nowizard"),
            checkResult);

    xm.gSettings.wizardSuppress = checkResult.value;
    xm.gSettings.majorVersion = 3;

    return ret;
};

xm.Synch = function() {
    xm.PerformAction("synch");
};

xm.PerformAction = function(action, arg) {
    var retval = { helpurl: null };

    try {
        var win = window.openDialog(
            "chrome://foxmarks/content/foxmarks-progress.xul", "_blank",
            "chrome,dialog,modal,centerscreen", action, retval, arg);
        if (retval.helpurl) {
            xm.OpenInNewWindow(retval.helpurl);   
        }
    } catch (e) {
        // pass through
    }
    return retval.status;
};

var XmarksDataServiceObserver = {
    os: Cc["@mozilla.org/observer-service;1"].
        getService(Ci.nsIObserverService),

    observe: function(subject, topic, data) {
        var result = eval("(" + data + ")");
        this.os.removeObserver(this, "foxmarks-dataservice");
        if (this.spinner) {
            this.spinner.hidden = true;
        }
        if (this.callback) {
            var callback = this.callback;
            this.callback = null;
            callback(result);
        }
    },

    start: function(text, spinner, callback) {
        this.os.addObserver(this, 
                "foxmarks-dataservice", false);
        this.text = text;
        this.spinner = spinner;
        this.callback = callback;
        if (this.spinner) {
            this.spinner.hidden = false;
        }
    }
};
var XmarksServiceObserver = {
    os: Cc["@mozilla.org/observer-service;1"].
        getService(Ci.nsIObserverService),

    observe: function(subject, topic, data) {
        if (topic == "foxmarks-service") {
            var result = eval("(" + data + ")");
            if (this.text && result.msg) {
                this.text.value = result.msg;
            }
            if (result.status != 1) {
                this.os.removeObserver(this, "foxmarks-service");
                this.os.removeObserver(this, "foxmarks-statechange");
                if (this.spinner) {
                    this.spinner.hidden = true;
                }
                if (this.callback) {
                    var callback = this.callback;
                    this.callback = null;
                    callback(result);
                }
            }
        } else if (topic == "foxmarks-statechange") {
            if (this.spinner) {
                this.spinner.hidden = (data != 'working');
            }
        }
    },

    start: function(text, spinner, callback) {
        this.os.addObserver(XmarksServiceObserver, "foxmarks-service", false);
        this.os.addObserver(XmarksServiceObserver, "foxmarks-statechange", 
            false);
        this.text = text;
        this.spinner = spinner;
        this.callback = callback;
        if (this.spinner) {
            this.spinner.hidden = false;
        }
    }
}

xm.TurboTagsCancel = function() {
    Xmarks.fms.datacancel();
};

xm.FetchTurboTags = function(url, text, spinner, callback) {
    XmarksDataServiceObserver.start(text, spinner, callback);
    if (!Xmarks.fms.getTurboTags(url)) {
        callback({status: 2, msg: "Whoops! We're busy!" });
    }
    return true;
};

xm.UpdateReview = function(url, url_id, title, description, rating, review, 
        post_to_fb, callback) {
    XmarksDataServiceObserver.start(null, null, callback);
    if (!Xmarks.fms.updateReview(url, url_id, title, description, rating, 
            review, post_to_fb)) {
        callback({status: 2, msg: "Whoops! We're busy!" });
    }
    return true;
};


xm.SimilarSitesCancel = function() {
    Xmarks.fms.datacancel();
};

xm.FetchSimilarSites = function(url, text, spinner, callback) {
    XmarksDataServiceObserver.start(text, spinner, callback);
    if (!Xmarks.fms.getSimilarSites(url)) {
        callback({status: 2, msg: "Whoops! We're busy!" });
    }
    return true;
};

xm.FetchProfileNames = function(text, spinner, menuPopup, callback) {
    XmarksServiceObserver.start(text, spinner, FetchProfileNamesCallback);
    if (!Xmarks.fms.getProfileNames()) {
        callback({status: 2, msg: "Whoops! We're busy!" });
    }

    function FetchProfileNamesCallback(response) {
        if (response.profiles) {
            var profiles = response.profiles;
            var count = 0;
            for (var i = 1; i < menuPopup.childNodes.length; ++i) {
                if (profiles[String(i)]) {
                    var name = profiles[String(i)];
                    menuPopup.childNodes[i].label = name;
                    menuPopup.childNodes[i].hidden = false;
                    count++;
                } else {
                    menuPopup.childNodes[i].hidden = true;
                }
            }
            if (callback) {
                callback({ status: response.status, count: count, 
                        profiles: profiles });
            }
        }
    }
};

xm.VerifyPINStatus = function(pin, text, spinner, callback) {
    XmarksServiceObserver.start(text, spinner, callback);
    Xmarks.fms.verifypin(pin);
};

xm.FetchAccountStatus = function(syncType, text, spinner, callback) {
    XmarksServiceObserver.start(text, spinner, callback);
    try {
        Xmarks.fms.status(syncType);
    } catch (e) {
        Xmarks.LogWrite("FetchAccountStatus failed: " + e.toSource());
        callback(typeof(e) == "number" ? e : 4);
    }
};

xm.FetchRevision = function(rev,callback) {
    XmarksServiceObserver.start("", null, callback);
    Xmarks.fms.getrevision(rev);
};

xm.FetchRevisions = function(callback) {
    XmarksServiceObserver.start("", null, callback);
    Xmarks.fms.getrevisions();
};
xm.FetchAccountExtStatus = function(syncType, text, spinner, callback) {
    XmarksServiceObserver.start(text, spinner, callback);
    Xmarks.fms.extstatus(syncType);
};

var inputTimer;
xm.handlePasswordMeter = function(id){
    if(inputTimer){
        window.clearTimeout(inputTimer);
        inputTimer = undefined;
    }

    inputTimer = window.setTimeout(function(){
        var txt = document.getElementById(id).value;
        var result = TestPassword(txt);

        if(result * 5 > 200 || result > 24){
            result = 40;
        }
        document.getElementById('passwordmeter').width = result * 5;
        if(txt.length < 4){
            document.getElementById('passwordStrength').style.color = 
                "#333";
            document.getElementById('passwordmeter').style.backgroundColor = 
                "#999";

            document.getElementById('passwordStrength').value =
                xm.Bundle().GetStringFromName("password.tooshort");
        }
        else if(result < 17){
            document.getElementById('passwordStrength').value =
                xm.Bundle().GetStringFromName("password.weak");
            document.getElementById('passwordStrength').style.color = 
                "#57040F";
            document.getElementById('passwordmeter').style.backgroundColor = 
                "#57040F";
        }
        else if(result < 24){
            document.getElementById('passwordStrength').value =
                xm.Bundle().GetStringFromName("password.good");
            document.getElementById('passwordStrength').style.color = 
                "#ED9D2B";
            document.getElementById('passwordmeter').style.backgroundColor = 
                "#ED9D2B";
        }
        else {
            document.getElementById('passwordStrength').value =
                xm.Bundle().GetStringFromName("password.strong");
            document.getElementById('passwordStrength').style.color = 
                "#2A911B";
            document.getElementById('passwordmeter').style.backgroundColor = 
                "#2A911B";

        }
        inputTimer = undefined;
    }, 500);
};

})();
