/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is JIM.
 *
 * The Initial Developer of the Original Code is
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * scripts.uiscripts.VCard
 *
 *
 */
ML.load("io/reader.js");
ML.load("utils/misc.js");
ML.load("xml/xmldomtraverse.js");
ML.load("xml/xmldomutils.js");
ML.load("xml/xmldombuilder.js");

function VCardHandler()
{
    this.bundle = getStringBundle("chrome://jim/locale/jim.properties");
}

function SetVCardValueAction(id)
{
    this.base = XMLDOMAction;
    this.base();
    this.id = id;
    this.attributes = {};
    this.phonesCount = 0;
    this.addressesCount = 0;
}

SetVCardValueAction.prototype =
{
    __proto__: XMLDOMAction.prototype,

    handle: function(dom)
    {
        document.getElementById(this.id).value = domToText(dom);
    },

    recover: function(namespaceURI, element, parent)
    {
        val = document.getElementById(this.id).value
        if (val)
            parent.addElement(namespaceURI, element).addText(val);
    },
}

VCardHandler.prototype =
{
    onLoad: function()
    {
        var tags, i, el;

        this.from = window.arguments[0];
        window.contact = this.from;

        if (this.from != jabberService.core.uidShort) {
            tags = document.getElementsByTagName("textbox");
            for (i = 0; i < tags.length; i++)
                tags[i].readonly = true;
            document.getElementById("jim-vcard-email-editpane").
                setAttribute("hidden", "true");
            document.getElementById("jim-vcard-phone-editpane").
                setAttribute("hidden", "true");
            document.getElementById("jim-vcard-address-editpane").
                setAttribute("hidden", "true");
            document.getElementById("jim.vcard.appearance.avatar").
                setAttribute("hidden", "true");
        } else {
            var uri, list, i;

            el = document.getElementById("jim-vcard-appearance-avatarbox");
            el.database.AddDataSource(jabberService.localRDF.DS);
            el.builder.rebuild();

            uri = jabberService.core.highlevel.avatars.getThisAvatar();

            this.selectAvatarByUri(uri);
        }

        if (this.from) {
            jabberService.core.iq.vCard.addObserver(this);
            jabberService.core.iq.vCard.getVCard(this.from);
            document.getElementById("jim.vcard.basic.jabberid").value =
                this.from;
        }
    },

    onUnload: function()
    {
        jabberService.core.iq.vCard.removeObserver(this);
    },

    onFinish: function()
    {
        var el = document.getElementById("jim-vcard-appearance-avatarbox");
        var list, i;

        list = el.childNodes;
        for (i = 0; i < list.length; i++)
            if (list[i].getAttribute("selected") == "true") {
                jabberService.core.highlevel.avatars.
                    setThisAvatar(list[i].getAttribute("src"));
                break;
            }
        if (i >= list.length)
            jabberService.core.highlevel.avatars.setThisAvatar(null);

        jabberService.core.iq.vCard.setVCard(this.getResultTree());

        return true;
    },

    onCategoryTreeSelect: function(event)
    {
        document.getElementById("category-deck").selectedPanel = 
            document.getElementById(event.target.contentView.
                getItemAtIndex(event.target.currentIndex).
                firstChild.firstChild.getAttribute("refid"));
    },

    setSelectedElement: function(element, value)
    {
        var el = element.parentNode.firstChild;

        while (el) {
            el.setAttribute("selected", "false");
            el = el.nextSibling;
        };

        if (value)
            element.setAttribute("selected", "true");
    },

    getSelectedElement: function(el)
    {
        el = el.firstChild;
        while (el) {
            if (el.getAttribute("selected") == "true")
                return el;
            el = el.nextSibling;
        }

        return null;
    },

    selectAvatarByUri: function(uri)
    {
        list = document.getElementById("jim-vcard-appearance-avatarbox").
            childNodes;

        for (i = 0; i < list.length; i++)
            if (list[i].getAttribute("src") == uri) {
                this.setSelectedElement(list[i], true);
                break;
            }
    },

    updateControls: function(element, prefix)
    {
        var elements, el, i;

        elements = element.getElementsByTagName("checkbox");

        for (i = 0; i < elements.length; i++)
            elements[i].checked = false;

        for (i in this.attributes) {
            el = document.getElementById(prefix + i);

            if (el) {
                if (el.nodeName == "checkbox")
                    el.checked = true;
                else
                    el.value = this.attributes[i];
            }
        }
    },

    updateNote: function(element, hash)
    {
        var el, el2, i, j;

        el = element.getElementsByTagName("description");

        for (i = 0; i < el.length; i++)
            if (el[i].getAttribute("related-field") == "attributes") {
                val = this.getAttributesTextual(hash);
                el[i].setAttribute("attributes", val[1]);
                el[i].firstChild.replaceData(0, 0xffff, val[0]);
            } else if (el[i].hasAttribute("related-field")) {
                el[i].setAttribute("value", this.attributes[
                    el[i].getAttribute("related-field")] || "");
            }
    },

    getValuesFromNote: function(element)
    {
        var el, el2, i, j;

        this.attributes = { };

        el = element.getElementsByTagName("description");

        for (i = 0; i < el.length; i++)
            if (el[i].getAttribute("related-field") == "attributes") {
                el2 = el[i].getAttribute("attributes").split(",");
                for (j = 0; j < el2.length; j++)
                    this.attributes[el2[j]] = true;
            } else if (el[i].hasAttribute("related-field")) {
                this.attributes[el[i].getAttribute("related-field")] =
                    el[i].getAttribute("value");
            }
    },

    getValuesFromControls: function(element)
    {
        var el, i;

        this.attributes = { };

        el = element.getElementsByTagName("textbox");
        for (i = 0; i < el.length; i++) {
            this.attributes[el[i].getAttribute("id").match(/\.([^.]+)$/)[1]] =
                el[i].value;
        }

        el = element.getElementsByTagName("checkbox");
        for (i = 0; i < el.length; i++)
            if (el[i].checked)
                this.attributes[el[i].getAttribute("id").match(/\.([^.]+$)/)[1]] = true;
    },

    buildTreeFromElement: function(element, ns, nodeName, parent)
    {
        var i, j, el;

        var notes = element.childNodes;

        for (i = 0; i < notes.length; i++) {
            this.getValuesFromNote(notes[i]);

            el = parent.addElement(ns, nodeName);
            for (j in this.attributes)
                if (this.attributes[j] == true)
                    el.addElement(ns, j);
                else
                    el.addElement(ns, j).
                        addText(this.attributes[j]);
        }
    },

    onRemoveNote: function(event, keyword)
    {
        var el = this.getSelectedElement(document.getElementById("jim-vcard-"+keyword+"-pane"));

        if (el)
            el.parentNode.removeChild(el);
    },

    onUpdateNote: function(event, keyword)
    {
        var el = this.getSelectedElement(document.getElementById("jim-vcard-"+keyword+"-pane"));

        if (el) {
            this.getValuesFromControls(document.getElementById("jim-vcard-"+keyword+"-editpane"));
            this.updateNote(el, this[keyword+"AttributesToProperties"]);
        }
    },

    onSelectNote: function(event, element, keyword)
    {
        this.getValuesFromNote(element);
        this.updateControls(
            document.getElementById("jim-vcard-"+keyword+"-editpane"), "jim.vcard."+keyword+".");
        this.setSelectedElement(element, true);
    },

    onAddPhone: function(event)
    {
        this.getValuesFromControls(
            document.getElementById("jim-vcard-phone-editpane"));
        this.addPhone();
    },

    onAddEmail: function(event)
    {
        this.getValuesFromControls(
            document.getElementById("jim-vcard-email-editpane"));
        this.addEmail();
    },

    onAddAddress: function(event)
    {
        this.getValuesFromControls(
            document.getElementById("jim-vcard-address-editpane"));
        this.addAddress();
    },

    onAvatarClick: function(event)
    {
        this.setSelectedElement(event.target,
            event.target.getAttribute("selected") != "true")
    },

    onAvatarLoad: function(event)
    {
        var filePicker = Components.classes["@mozilla.org/filepicker;1"].
            getService(Components.interfaces.nsIFilePicker);

        filePicker.init(window, this.bundle.GetStringFromName("pickAvatarDialogTitle"),
            filePicker.modeOpen);
        filePicker.appendFilters(filePicker.filterAll | filePicker.filterImages);
        if (filePicker.show() == filePicker.returnOK) {
            var uri = jabberService.core.highlevel.avatars.addFileToCache(
                new Reader(filePicker.fileURL.spec));
            setTimeout(function(_this, uri) { _this.selectAvatarByUri(uri) }, 100, this, uri);
        }
    },

    onUrlOpen: function(event)
    {
        var url = document.getElementById("jim.vcard.personal.url").value;
        if (url)
            window.open(url, "_blank");
    },

    onOpenLink: function(url)
    {
        window.location.href = url;
    },

    onIQVCardError: function(errorCode, errorText)
    {
    },

    onIQVCard: function(from, tag)
    {
        var idx = from.indexOf("/");
        if (idx > 0)
            from = from.substring(0, idx);

        if (this.from == from)
            xmlDOMTraverse(tag, "vCard", this.actionTree, this);
    },

    reset: function()
    {
    },

    getAttributesTextual: function(hash)
    {
        var text, attribs;

        for (i in this.attributes)
            if (hash[i])
                if (text) {
                    text += ", " + this.bundle.GetStringFromName(hash[i]);
                    attribs += ","+i;
                } else {
                    text = this.bundle.GetStringFromName(hash[i]);
                    attribs = i;
                }
        if (text)
            return [text, attribs];
        return ["", ""];
    },

    createNote: function(hash, prefix)
    {
        var grid, rows, row, el, text;

        grid = document.createElement("grid");

        rows = document.createElement("columns");
        grid.appendChild(rows);

        row =  document.createElement("column");
        rows.appendChild(row);

        row =  document.createElement("column");
        rows.appendChild(row);

        rows = document.createElement("rows");
        grid.appendChild(rows);

        for (i = 2; i < arguments.length; i++) {
            row = document.createElement("row");
            rows.appendChild(row);

            el =  document.createElement("description");
            el.setAttribute("value", this.bundle.
                GetStringFromName(prefix+arguments[i].toLowerCase()));
            row.appendChild(el);

            el =  document.createElement("description");
            el.setAttribute("flex", "1");
            el.setAttribute("align", "start");
            el.setAttribute("value", this.attributes[arguments[i]] || "");
            el.setAttribute("related-field", arguments[i]);
            row.appendChild(el);
        }

        if (hash) {
            row = document.createElement("row");
            rows.appendChild(row);

            el =  document.createElement("description");
            el.setAttribute("align", "start");
            el.setAttribute("value", this.bundle.GetStringFromName(prefix+"attributes"));
            row.appendChild(el);

            text = this.getAttributesTextual(hash);

            el =  document.createElement("description");
            el.setAttribute("flex", "1");
            el.setAttribute("related-field", "attributes");
            el.setAttribute("attributes", text[1]);
            el.appendChild(document.createTextNode(text[0]));
            row.appendChild(el);
        }
        return grid;
    },

    addPhone: function()
    {
        var grid;

        if (this.attributes.NUMBER) {
            grid = this.createNote(
                this.phoneAttributesToProperties,
                "vcard.phone.",
                "NUMBER");
            grid.setAttribute("onclick", "vCardHandler.onSelectNote(event, this, 'phone')");
            document.getElementById("jim-vcard-phone-pane").appendChild(grid);
        }
    },

    buildPhone: function(ns, nodeName, parent)
    {
        this.buildTreeFromElement(
            document.getElementById("jim-vcard-phone-pane"),
            ns, nodeName, parent);
    },

    addEmail: function()
    {
        var grid, link;

        if (this.attributes.USERID) {
            grid = this.createNote(
                this.phoneAttributesToProperties,
                "vcard.email.",
                "USERID");
            link = grid.getElementsByAttribute("related-field", "USERID")[0];
            if (link) {
                link.setAttribute("class", "link");
                link.setAttribute("onclick", "vCardHandler.onOpenLink('mailto:"+
                    this.attributes.USERID+"');event.stopPropagation()");
            }
            grid.setAttribute("onclick", "vCardHandler.onSelectNote(event, this, 'email')");
            document.getElementById("jim-vcard-email-pane").appendChild(grid);
        }
    },

    buildEmail: function(ns, nodeName, parent)
    {
        this.buildTreeFromElement(
            document.getElementById("jim-vcard-email-pane"),
            ns, nodeName, parent);
    },

    addAddress: function()
    {
        var grid;

        if (this.attributes.POBOX || this.attributes.EXTADR ||
                this.attributes.STREET || this.attributes.STREET ||
                this.attributes.REGION || this.attributes.PCODE ||
                this.attributes.CTRY)
        {
            grid = this.createNote(
                this.addressAttributesToProperties,
                "vcard.address.",
                "LOCALITY",
                "STREET",
                "EXTADD",
                "REGION",
                "CTRY",
                "PCODE",
                "POBOX");
            grid.setAttribute("onclick", "vCardHandler.onSelectNote(event, this, 'address')");
            document.getElementById("jim-vcard-address-pane").appendChild(grid);
        }
    },

    buildAddress: function(ns, nodeName, parent)
    {
        this.buildTreeFromElement(
            document.getElementById("jim-vcard-address-pane"),
            ns, nodeName, parent);
    },

    resetAttributes: function()
    {
        this.attributes = { };
    },

    setBoolAttribute: function(dom)
    {
        this.attributes[dom.localName] = true;
    },

    setAttribute: function(dom)
    {
        this.attributes[dom.localName] = domToText(dom);
    },

    concatAttributes: function(dom)
    {
        if (dom.localName in this.attributes)
            this.attributes[dom.localName] += domToText(dom);
        else
            this.attributes[dom.localName] = domToText(dom);
    },

    getResultTree: function()
    {
        var root = DB.createElement("vcard-temp", "vCard");
        this.getResultTreeRec(this.actionTree, "vcard-temp", root, this);
        return root;
    },

    getResultTreeRec: function(actionTree, ns, parent, val)
    {
        var action, recover, i, root;

        for (i in actionTree) {
            action = actionTree[i];
            if (action instanceof XMLDOMAction)
                action.recover(ns, i, parent, val);
            else {
                if (recover = action.__RECOVER__) {
                    if (typeof(recover) == "function")
                        recover(ns, i, parent, val);
                    else if (recover instanceof XMLDOMAction)
                        recover.recover(ns, i, parent, val);
                } else {
                    root = parent.addElement(ns, i);
                    this.getResultTreeRec(action, ns, root, val);
                    if (!root.hasChildNodes)
                        parent.removeChild(root);
                }
            }
        }
    },

    phoneAttributesToProperties: {
        HOME:  "vcard.phone.home",
        WORK:  "vcard.phone.work",
        VOICE: "vcard.phone.voice",
        FAX:   "vcard.phone.fax",
        PAGER: "vcard.phone.pager",
        MSG:   "vcard.phone.msg",
        CELL:  "vcard.phone.cell",
        VIDEO: "vcard.phone.video",
        BBS:   "vcard.phone.bbs",
        MODEM: "vcard.phone.modem",
        ISDN:  "vcard.phone.isdn",
        PCS:   "vcard.phone.pcs",
        PREF:  "vcard.phone.pref",
    },

    emailAttributesToProperties: {
        HOME:     "vcard.email.home",
        WORK:     "vcard.email.work",
        INTERNET: "vcard.email.internet",
        X400:     "vcard.email.x400",
    },

    addressAttributesToProperties: {
        HOME:     "vcard.address.home",
        WORK:     "vcard.address.work",
        POSTAL:   "vcard.address.postal",
        PARCEL:   "vcard.address.parcel",
        DOM:      "vcard.address.dom",
        INTL:     "vcard.address.intl",
        PREF:     "vcard.address.pref",
    },

    actionTree: {
        FN: new SetVCardValueAction("jim.vcard.basic.fullname"),
        N: {
            FAMILY:   new SetVCardValueAction("jim.vcard.basic.family"),
            GIVEN:    new SetVCardValueAction("jim.vcard.basic.given"),
            MIDDLE:   new SetVCardValueAction("jim.vcard.basic.middle"),
            PREFIX:   new SetVCardValueAction("jim.vcard.basic.prefix"),
            SUFFIX:   new SetVCardValueAction("jim.vcard.basic.suffix"),
        },
        NICKNAME: new SetVCardValueAction("jim.vcard.basic.nickname"),
        URL:      new SetVCardValueAction("jim.vcard.personal.url"),
        BDAY:     new SetVCardValueAction("jim.vcard.personal.bday"),
        TEL: {
            __RECOVER__:    function(ns, nodeName, parent, _this) { return _this.buildPhone(ns, nodeName, parent);},
            __INITIALIZE__: function(dom, _this) { _this.resetAttributes();},
            __FINALIZE__:   function(dom, _this) { _this.addPhone();},
            HOME:           function(dom, _this) { _this.setBoolAttribute(dom);},
            WORK:           function(dom, _this) { _this.setBoolAttribute(dom);},
            VOICE:          function(dom, _this) { _this.setBoolAttribute(dom);},
            FAX:            function(dom, _this) { _this.setBoolAttribute(dom);},
            PAGER:          function(dom, _this) { _this.setBoolAttribute(dom);},
            MSG:            function(dom, _this) { _this.setBoolAttribute(dom);},
            CELL:           function(dom, _this) { _this.setBoolAttribute(dom);},
            VIDEO:          function(dom, _this) { _this.setBoolAttribute(dom);},
            BBS:            function(dom, _this) { _this.setBoolAttribute(dom);},
            MODEM:          function(dom, _this) { _this.setBoolAttribute(dom);},
            ISDN:           function(dom, _this) { _this.setBoolAttribute(dom);},
            PCS:            function(dom, _this) { _this.setBoolAttribute(dom);},
            PREF:           function(dom, _this) { _this.setBoolAttribute(dom);},
            NUMBER:         function(dom, _this) { _this.setAttribute(dom);},
        },
        EMAIL: {
            __RECOVER__:    function(ns, nodeName, parent, _this) { return _this.buildEmail(ns, nodeName, parent);},
            __INITIALIZE__: function(dom, _this) { _this.resetAttributes();},
            __FINALIZE__:   function(dom, _this) { _this.addEmail();},
            HOME:           function(dom, _this) { _this.setBoolAttribute(dom);},
            WORK:           function(dom, _this) { _this.setBoolAttribute(dom);},
            INTERNET:       function(dom, _this) { _this.setBoolAttribute(dom);},
            X400:           function(dom, _this) { _this.setBoolAttribute(dom);},
            USERID:         function(dom, _this) { _this.setAttribute(dom);},
        },
        ADR: {
            __RECOVER__:    function(ns, nodeName, parent, _this) { return _this.buildAddress(ns, nodeName, parent);},
            __INITIALIZE__: function(dom, _this) { _this.resetAttributes();},
            __FINALIZE__:   function(dom, _this) { _this.addAddress();},
            HOME:           function(dom, _this) { _this.setBoolAttribute(dom);},
            WORK:           function(dom, _this) { _this.setBoolAttribute(dom);},
            POSTAL:         function(dom, _this) { _this.setBoolAttribute(dom);},
            PARCEL:         function(dom, _this) { _this.setBoolAttribute(dom);},
            DOM:            function(dom, _this) { _this.setBoolAttribute(dom);},
            INTL:           function(dom, _this) { _this.setBoolAttribute(dom);},
            PREF:           function(dom, _this) { _this.setBoolAttribute(dom);},
            POBOX:          function(dom, _this) { _this.setAttribute(dom);},
            EXTADD:         function(dom, _this) { _this.setAttribute(dom);},
			STREET:         function(dom, _this) { _this.setAttribute(dom);},
			LOCALITY:       function(dom, _this) { _this.setAttribute(dom);},
			REGION:         function(dom, _this) { _this.setAttribute(dom);},
			PCODE:          function(dom, _this) { _this.setAttribute(dom);},
			CTRY:           function(dom, _this) { _this.setAttribute(dom);},
        },
        TZ:         new SetVCardValueAction("jim.vcard.location.tz"),
        GEO: {
            LAT: new SetVCardValueAction("jim.vcard.location.lat"),
            LON: new SetVCardValueAction("jim.vcard.location.lon"),
        }
    }
}

var vCardHandler = new VCardHandler();