var fsLoccus = {
    /**
    * Store the current language code
    */
    language: ''
    ,
    /**
    * Get all labels with "labelid:" from the HTML, get their class item value and
    * use that to look up in the labels.xml, get the label value and return it into
    * the innerHTML
    */
    fillUpLabels: function()
    {

        var elmLabels = fs.getElementsByClassNameItemName('labelid');
        var strLabelId = null;
        for (var i=0; i<elmLabels.length; i++) {
            strLabelId = fs.getElementClassNameItemValue(elmLabels[i], 'labelid');
            elmLabels[i].innerHTML = this.getLabel(strLabelId);
        }
    }
    ,
    /**
    * Get the label value by supplying the labelid
    */
    getLabel: function(strLabelId)
    {
        var strRawLabel = this.getRawLabel(strLabelId);
        var strCustomFilledLabel = this.fillCustomVariable(strRawLabel);
        var strCustomAndSnippetFilledLabel = this.fillSnippet(strLabelId, strCustomFilledLabel);

        return strCustomAndSnippetFilledLabel;
    }
    ,
    getRawLabel: function(strLabelId)
    {
        try {
        var xmlLabel = fsXml.open([fs.getContainingFolder(),'/',fsConfig.PATH_TO_LANGUAGE_XMLS, this.language, '/labels.xml'].join(''));
        var strRawLabel = fsXml.getTextByXpath(xmlLabel, '/labels/label[@id="' + strLabelId + '"]/text()');

        return strRawLabel;
        } catch(e) {
        }
    }
    ,
    /**
    * Replace all the custom variables in the string supplied by looking up in
    * the customs.xml and return it to the caller
    */
    fillCustomVariable: function(strLabelWithCustomVariable)
    {
        if (/\{[A-Za-z]{1}[A-Za-z0-9-]+\}/.test(strLabelWithCustomVariable)) {
            var arrCustomVariable = strLabelWithCustomVariable.match(new RegExp(/\{([A-Za-z]{1}[A-Za-z0-9-]+)\}/));
            var strCustomVariableWithCurly = arrCustomVariable[0];
            var strCustomVariableName = arrCustomVariable[1];
            strLabelWithCustomVariable = strLabelWithCustomVariable.replace(strCustomVariableWithCurly, fsLoccus.getCustomVariableValue(strCustomVariableName));
            strLabelWithCustomVariable = this.fillCustomVariable(strLabelWithCustomVariable);
        }

        return strLabelWithCustomVariable;
    }
    ,
    /**
    * Get the custom variable value by supplying the custom variable name
    */
    getCustomVariableValue: function(strCustomVariableName)
    {
        var xmlCustom = fsXml.open(fs.getContainingFolder() + '/' + fsConfig.PATH_TO_XMLS + 'customs.xml');
        var strXpath = ['/customs/strings/string[@id="', strCustomVariableName, '"]/item[@lang="', this.language,'"]/text()'].join('');
        var elmCustomValue = fsXml.getElementByXpath(xmlCustom, strXpath);

        if (elmCustomValue === null) {
            strXpath = ['/customs/strings/string[@id="', strCustomVariableName, '"]/item[@lang=""]/text()'].join('');
            elmCustomValue = fsXml.getElementByXpath(xmlCustom, strXpath);
        }

        if (elmCustomValue === null) {
            return "&nbsp;";
        } else if (elmCustomValue.nodeValue != ''){
            return elmCustomValue.nodeValue;
        } else if (elmCustomValue.textContent != ''){
            return elmCustomValue.textContent;
        }
    }
    /**
    * Supply the label id and the label itself, all the snippet variable identifier will be replaced
    */
    ,
    fillSnippet: function(strLabelId, strLabel)
    {
        //var re = /\{([0-9]{1})}([^\{]+)\{\/\1}/g;
        //var strLabelCopy = strLabel;
        //while (aMatch = re.exec(strLabel)) {
        //    strLabelCopy = strLabelCopy.replace(aMatch[0], this.getProcessedSnippet(strLabelId, aMatch[1], aMatch[2]));
        //}
        //return strLabelCopy;
        var strRe = '\{([0-9]{1})}([^\{]+)\{/\\1}';
        var arrMatch = strLabel.match(new RegExp(strRe,'g'));
        if (arrMatch != null) {
            var arrMatchSingle = null;
            for (var i=0; i<arrMatch.length; i++) {
                arrMatchSingle = arrMatch[i].match(strRe);
                strLabel = strLabel.replace(arrMatch[i], this.getProcessedSnippet(strLabelId, arrMatchSingle[1], arrMatchSingle[2]));
            }
        }

        return strLabel;
    }
    ,
    /**
    * Get associated code snippets and properties, combine them together and return
    * it to the callee
    */
    getProcessedSnippet: function(strLabelId, strItemId, strLabelString)
    {
        /* open diretives.xml and get the snippet-id, and use it to get the raw snippet */
        var strSnippetId = this.getSnippetId(strLabelId, strItemId);
        var strRawSnippet = this.getRawSnippet(strSnippetId);
        var objValue = this.getSnippetPlaceHolderValue(strLabelId, strItemId, strLabelString);
        var strProcessedSnippet = this.insertResultIntoString(strRawSnippet, objValue);

        return strProcessedSnippet;
    }
    ,
    /**
    * Get the snippet ID from directives.xml, given a label ID and the item ID
    */
    getSnippetId: function(strLabelId, strItemId)
    {
        var xmlDirectives = fsXml.open(fs.getContainingFolder() + '/' + fsConfig.PATH_TO_XMLS + 'directives.xml');
        var strXpath = '/directives/directive[@id="' + strLabelId + '"]/item[@id="' + strItemId + '"]/@snippet-id';
        var strSnippetId = fsXml.getTextByXpath(xmlDirectives, strXpath);

        return strSnippetId;
    }
    ,
    /**
    * Get the raw snippet string from snippets.xml given a snippet ID
    */
    getRawSnippet: function(strSnippetId)
    {
        var xmlDirectives = fsXml.open(fs.getContainingFolder() + '/' + fsConfig.PATH_TO_XMLS + 'snippets.xml');
        var strSnippet = fsXml.getTextByXpath(xmlDirectives, '/snippets/snippet[@id="'+strSnippetId+'"]/text()');

        return strSnippet;
    }
    ,
    /**
    * Based on directives.xml, get the associated value from customs.xml and labels.xml
    */
    getSnippetPlaceHolderValue: function(strLabelId, strItemId, strLabelString)
    {
        var xmlDirectives = fsXml.open(fs.getContainingFolder() + '/' + fsConfig.PATH_TO_XMLS + 'directives.xml');
        var strXpath = ['directives/directive[@id="',strLabelId,'"]/item[@id="', strItemId, '"]/snippet-item'].join('');
        var strElmValue = '';
        var arrElm = fsXml.getElementsByXpath(xmlDirectives, strXpath);
        var objParam = {};

        for (var i=0; i<arrElm.length; i++) {
            strId = arrElm[i].getAttribute('id');
            strElmValue = arrElm[i].hasChildNodes() ? arrElm[i].childNodes[0].nodeValue : '';
            strElmReference = (arrElm[i].getAttribute('reference') != null) ? arrElm[i].getAttribute('reference').toLowerCase() : null;

            if (strElmReference === null) {
                objParam[strId] = strElmValue;
            } else if (strElmReference == 'label-item') {
                objParam[strId] = strLabelString;
            } else if (strElmReference == 'label') {
                objParam[strId] = this.getLabel(strElmValue);
            } else if (strElmReference == 'custom') {
                objParam[strId] = this.getCustomVariableValue(strElmValue);
            }
        }

        return objParam;
    }
    ,
    /**
    * Get labels with variables and the variables values, mix them up and return
    */
    insertResultIntoString: function(sSnippetString, oResultParam) {
        var sIdWithTag = '';
        var sIdValue = '';

        for (var sId in oResultParam) {
            sIdWithTag = sId.replace(/(.+)/, '{$1}');
            sIdValue = oResultParam[sId];
            sSnippetString = sSnippetString.replace(sIdWithTag,sIdValue);
        }

        return sSnippetString;
    }
    ,
    setLanguage: function(sLang) {
        this.language = sLang;
    }
    ,
    toString: function() {
        return 'fsLoccus';
    },
    update: function(event_name) {
        if (event_name == 'languagecodechangeevent') {
            this.language = fsLanguage.languageCode;
        }
    }
}
