RED.editor.envVarList = (function() {

    var currentLocale = 'en-US';
    const DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
    const DEFAULT_ENV_TYPE_LIST_INC_CONFTYPES = ['str','num','bool','json','bin','env','conf-types'];
    const DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred','jsonata'];

    /**
     * Create env var edit interface
     * @param container - container
     * @param node - subflow node
     */
    function buildPropertiesList(envContainer, node) {
        if(RED.editor.envVarList.debug) { console.log('envVarList: buildPropertiesList', envContainer, node) }
        const isTemplateNode = (node.type === "subflow");

        envContainer
            .css({
                'min-height':'150px',
                'min-width':'450px'
            })
            .editableList({
                header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
                addItem: function(container, i, opt) {
                    // If this is an instance node, these are properties unique to
                    // this instance - ie opt.parent will not be defined.

                    if (isTemplateNode) {
                        container.addClass("red-ui-editor-subflow-env-editable")
                    }

                    var envRow = $('<div/>').appendTo(container);
                    var nameField = null;
                    var valueField = null;

                    nameField = $('<input/>', {
                        class: "node-input-env-name",
                        type: "text",
                        placeholder: RED._("common.label.name")
                    }).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
                    valueField = $('<input/>',{
                        style: "width:100%",
                        class: "node-input-env-value",
                        type: "text",
                    }).attr("autocomplete","disable").appendTo(envRow);
                    var types = (opt.ui && opt.ui.opts && opt.ui.opts.types);
                    if (!types) {
                        types = isTemplateNode ? DEFAULT_ENV_TYPE_LIST : DEFAULT_ENV_TYPE_LIST_INC_CRED;
                    }
                    valueField.typedInput({default:'str',types:types});
                    valueField.typedInput('type', opt.type);
                    if (opt.type === "cred") {
                        if (opt.value) {
                            valueField.typedInput('value', opt.value);
                        } else if (node.credentials && node.credentials[opt.name]) {
                            valueField.typedInput('value', node.credentials[opt.name]);
                        } else if (node.credentials && node.credentials['has_'+opt.name]) {
                            valueField.typedInput('value', "__PWRD__");
                        } else {
                            valueField.typedInput('value', "");
                        }
                    } else {
                        valueField.typedInput('value', opt.value);
                    }


                    opt.nameField = nameField;
                    opt.valueField = valueField;

                    var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
                    $('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
                    var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
                    actionButton.on("click", function(evt) {
                        evt.preventDefault();
                        removeTip.close();
                        container.parent().addClass("red-ui-editableList-item-deleting")
                        container.fadeOut(300, function() {
                            envContainer.editableList('removeItem',opt);
                        });
                    });

                    if (isTemplateNode) {
                        // Add the UI customisation row
                        // if `opt.ui` does not exist, then apply defaults. If these
                        // defaults do not change then they will get stripped off
                        // before saving.
                        if (opt.type === 'conf-types') {
                            opt.ui = opt.ui || {
                                icon: "fa fa-cog",
                                type: "conf-types",
                                opts: {opts:[]}
                            }
                            opt.ui.type = "conf-types";
                        } else if (opt.type === 'cred') {
                            opt.ui = opt.ui || {
                                icon: "",
                                type: "cred"
                            }
                            opt.ui.type = "cred";
                        } else {
                            opt.ui = opt.ui || {
                                icon: "",
                                type: "input",
                                opts: {types:DEFAULT_ENV_TYPE_LIST}
                            }
                        }
                        opt.ui.label = opt.ui.label || {};
                        opt.ui.type = opt.ui.type || "input";
                        if ((opt.ui.type === "cred") &&
                            opt.ui.opts &&
                            opt.ui.opts.types) {
                            opt.ui.type = "input";
                        }

                        var uiRow = $('<div/>').appendTo(container).hide();
                        // save current info for reverting on cancel
                        // var copy = $.extend(true, {}, ui);

                         $('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
                            evt.preventDefault();
                            if ($(this).hasClass('expanded')) {
                                uiRow.slideUp();
                                $(this).removeClass('expanded');
                            } else {
                                uiRow.slideDown();
                                $(this).addClass('expanded');
                            }
                        });

                        buildEnvEditRow(uiRow, opt, nameField, valueField);
                        nameField.trigger('change');
                    }
                },
                sortable: true,
                removable: false
            });
        var parentEnv = {};
        var envList = [];
        if (/^subflow:/.test(node.type)) {
            var subflowDef = RED.nodes.subflow(node.type.substring(8));
            if (subflowDef.env) {
                subflowDef.env.forEach(function(env) {
                    var item = {
                        name:env.name,
                        parent: {
                            type: env.type,
                            value: env.value,
                            ui: env.ui
                        }
                    }
                    envList.push(item);
                    parentEnv[env.name] = item;
                })
            }
        }

        if (node.env) {
            for (var i = 0; i < node.env.length; i++) {
                var env = node.env[i];
                if (parentEnv.hasOwnProperty(env.name)) {
                    parentEnv[env.name].type = env.type;
                    parentEnv[env.name].value = env.value;
                } else {
                    envList.push({
                        name: env.name,
                        type: env.type,
                        value: env.value,
                        ui: env.ui
                    });
                }
            }
        }
        envList.forEach(function(env) {
            if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
                return;
            }
            if (!isTemplateNode && env.parent) {
                return;
            }
            envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
        });
    }


    /**
     * Create UI edit interface for environment variable
     * @param container - container
     * @param env - env var definition
     * @param nameField - name field of env var
     * @param valueField - value field of env var
     */
     function buildEnvEditRow(container, opt, nameField, valueField) {
        const ui = opt.ui
        if(RED.editor.envVarList.debug) { console.log('envVarList: buildEnvEditRow', container, ui, nameField, valueField) }
         container.addClass("red-ui-editor-subflow-env-ui-row")
         var topRow = $('<div></div>').appendTo(container);
         $('<div></div>').appendTo(topRow);
         $('<div>').text(RED._("editor.icon")).appendTo(topRow);
         $('<div>').text(RED._("editor.label")).appendTo(topRow);
         $('<div class="red-env-ui-input-type-col">').text(RED._("editor.inputType")).appendTo(topRow);

         var row = $('<div></div>').appendTo(container);
         $('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
         var typeOptions = {
            'input': {types:DEFAULT_ENV_TYPE_LIST_INC_CONFTYPES},
            'select': {opts:[]},
            'spinner': {},
            'cred': {}
         };
         if (ui.opts) {
             typeOptions[ui.type] = ui.opts;
         } else {
             // Pick up the default values if not otherwise provided
             ui.opts = typeOptions[ui.type];
         }
         var iconCell = $('<div></div>').appendTo(row);

         var iconButton = $('<a href="#"></a>').appendTo(iconCell);
         iconButton.on("click", function(evt) {
             evt.preventDefault();
             var icon = ui.icon || "";
             var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
             RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
                 iconButton.empty();
                 var path = newIcon || "";
                 var newPath = RED.utils.separateIconPath(path);
                 if (newPath) {
                     $('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
                 }
                 ui.icon = path;
             });
         })

         if (ui.icon) {
             var newPath = RED.utils.separateIconPath(ui.icon);
             $('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
         }

         var labelCell = $('<div></div>').appendTo(row);

         var label = ui.label && ui.label[currentLocale] || "";
         var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
         ui.labelField = labelInput;
         labelInput.on('change', function(evt) {
             ui.label = ui.label || {};
             var val = $(this).val().trim();
             if (val === "") {
                 delete ui.label[currentLocale];
             } else {
                 ui.label[currentLocale] = val;
             }
         })
         var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
         RED.popover.tooltip(labelIcon,function() {
             var langs = Object.keys(ui.label);
             var content = $("<div>");
             if (langs.indexOf(currentLocale) === -1) {
                 langs.push(currentLocale);
                 langs.sort();
             }
             langs.forEach(function(l) {
                 var row = $('<div>').appendTo(content);
                 $('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
                 $('<span>').text(ui.label[l]||"").appendTo(row);
             });
             return content;
         })

         nameField.on('change',function(evt) {
            labelInput.attr("placeholder",$(this).val())
        });

        var inputCell = $('<div class="red-env-ui-input-type-col"></div>').appendTo(row);
        var uiInputTypeInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
        if (ui.type === "input") {
            uiInputTypeInput.val(ui.opts.types.join(","));
        }
        var checkbox;
        var selectBox;

        // the options presented in the UI section for an "input" type selection
        uiInputTypeInput.typedInput({
            types: [
                {
                    value:"input",
                    label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
                        {value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
                        {value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
                        {value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
                        {value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
                        {value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
                        {value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
                        {value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
                    ],
                    default: DEFAULT_ENV_TYPE_LIST,
                    valueLabel: function(container,value) {
                        container.css("padding",0);
                        var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);

                        var input = $('<div class="placeholder-input">').appendTo(innerContainer);
                        $('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
                        if (value.length) {
                            value.forEach(function(v) {
                                if (!/^fa /.test(v.icon)) {
                                    $('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
                                } else {
                                    var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
                                    $("<i>",{class: v.icon}).appendTo(s);
                                }
                            })
                        } else {
                            $('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
                        }
                    }
                },
                {
                    value: "cred",
                    label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
                    valueLabel: function(container,value) {
                        container.css("padding",0);
                        var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
                            "border-top-right-radius": "4px",
                            "border-bottom-right-radius": "4px"
                        }).appendTo(container);
                        $('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
                    }
                },
                {
                    value:"select",
                    label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
                    valueLabel: function(container,value) {
                        container.css("padding","0");

                        selectBox = $('<select></select>').appendTo(container);
                        if (ui.opts && Array.isArray(ui.opts.opts)) {
                            ui.opts.opts.forEach(function(o) {
                                var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
                                // $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
                                $('<option>').val(o.v).text(label).appendTo(selectBox);
                            })
                        }
                        selectBox.on('change', function(evt) {
                            var v = selectBox.val();
                            // var parts = v.split(":");
                            // var t = parts.shift();
                            // v = parts.join(":");
                            //
                            // valueField.typedInput("type",'str')
                            valueField.typedInput("value",v)
                        });
                        selectBox.val(valueField.typedInput("value"));
                        // selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
                    },
                    expand: {
                        icon: "fa-caret-down",
                        minWidth: 400,
                        content: function(container) {
                            var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
                            var optList = $('<ol>').appendTo(content).editableList({
                                header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
                                addItem: function(row,index,itemData) {
                                    var labelDiv = $('<div>').appendTo(row);
                                    var label = lookupLabel(itemData.l, "", currentLocale);
                                    itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
                                    itemData.label.on('keydown', function(evt) {
                                        if (evt.keyCode === 13) {
                                            itemData.input.focus();
                                            evt.preventDefault();
                                        }
                                    });
                                    var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
                                    RED.popover.tooltip(labelIcon,function() {
                                        return currentLocale;
                                    })
                                    itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);

                                    // Problem using a TI here:
                                    //  - this is in a popout panel
                                    //  - clicking the expand button in the TI will close the parent edit tray
                                    //    and open the type editor.
                                    //  - but it leaves the popout panel over the top.
                                    //  - there is no way to get back to the popout panel after closing the type editor
                                    //.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
                                    itemData.input.on('keydown', function(evt) {
                                        if (evt.keyCode === 13) {
                                            // Enter or Tab
                                            var index = optList.editableList('indexOf',itemData);
                                            var length = optList.editableList('length');
                                            if (index + 1 === length) {
                                                var newItem = {};
                                                optList.editableList('addItem',newItem);
                                                setTimeout(function() {
                                                    if (newItem.label) {
                                                        newItem.label.focus();
                                                    }
                                                },100)
                                            } else {
                                                var nextItem = optList.editableList('getItemAt',index+1);
                                                if (nextItem.label) {
                                                    nextItem.label.focus()
                                                }
                                            }
                                            evt.preventDefault();
                                        }
                                    });
                                },
                                sortable: true,
                                removable: true,
                                height: 160
                            })
                            if (ui.opts.opts.length > 0) {
                                ui.opts.opts.forEach(function(o) {
                                    optList.editableList('addItem',$.extend(true,{},o))
                                })
                            } else {
                                optList.editableList('addItem',{})
                            }
                            return {
                                onclose: function() {
                                    var items = optList.editableList('items');
                                    var vals = [];
                                    items.each(function (i,el) {
                                        var data = el.data('data');
                                        var l = data.label.val().trim();
                                        var v = data.input.val();
                                        // var t = data.input.typedInput('type');
                                        // var v = data.input.typedInput('value');
                                        if (l.length > 0) {
                                            data.l = data.l || {};
                                            data.l[currentLocale] = l;
                                        }
                                        data.v = v;

                                        if (l.length > 0 || v.length > 0) {
                                            var val = {l:data.l,v:data.v};
                                            // if (t !== 'str') {
                                            //     val.t = t;
                                            // }
                                            vals.push(val);
                                        }
                                    });
                                    ui.opts.opts = vals;
                                    uiInputTypeInput.typedInput('value',Date.now())
                                }
                            }
                        }
                    }
                },
                {
                    value:"checkbox",
                    label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
                    valueLabel: function(container,value) {
                        container.css("padding",0);
                        checkbox = $('<input type="checkbox">').appendTo(container);
                        checkbox.on('change', function(evt) {
                            valueField.typedInput('value',$(this).prop('checked')?"true":"false");
                        })
                        checkbox.prop('checked',valueField.typedInput('value')==="true");
                    }
                },
                {
                    value:"spinner",
                    label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
                    valueLabel: function(container,value) {
                        container.css("padding",0);
                        var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);

                        var input = $('<div class="placeholder-input">').appendTo(innerContainer);
                        $('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);

                        var min = ui.opts && ui.opts.min;
                        var max = ui.opts && ui.opts.max;
                        var label = "";
                        if (min !== undefined && max !== undefined) {
                            label = Math.min(min,max)+" - "+Math.max(min,max);
                        } else if (min !== undefined) {
                            label = "> "+min;
                        } else if (max !== undefined) {
                            label = "< "+max;
                        }
                        $('<span>').css("margin-left","15px").text(label).appendTo(input);
                    },
                    expand: {
                        icon: "fa-caret-down",
                        content: function(container) {
                            var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
                            content.css("padding","8px 5px")
                            var min = ui.opts.min;
                            var max = ui.opts.max;
                            var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
                            minInput.val(min);
                            var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
                            maxInput.val(max);
                            $('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
                            $('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
                            return {
                                onclose: function() {
                                    var min = minInput.val().trim();
                                    var max = maxInput.val().trim();
                                    if (min !== "") {
                                        ui.opts.min = parseInt(min);
                                    } else {
                                        delete ui.opts.min;
                                    }
                                    if (max !== "") {
                                        ui.opts.max = parseInt(max);
                                    } else {
                                        delete ui.opts.max;
                                    }
                                    uiInputTypeInput.typedInput('value',Date.now())
                                }
                            }
                        }
                    }
                },
                'conf-types',
                {
                    value:"none",
                    label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
                },
                {
                    value:"hide",
                    label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
                }
            ],
            default: 'none'
        }).on("typedinputtypechange", function(evt,type) {
            ui.type = $(this).typedInput("type");
            ui.opts = typeOptions[ui.type];
            if (ui.type === 'input') {
                // In the case of 'input' type, the typedInput uses the multiple-option
                // mode. Its value needs to be set to a comma-separately list of the
                // selected options.
                uiInputTypeInput.typedInput('value',ui.opts.types.join(","))
            } else if (ui.type === 'conf-types') {
                // In the case of 'conf-types' type, the typedInput will be populated
                // with a list of all config nodes types installed.
                // Restore the value to the last selected type
                uiInputTypeInput.typedInput('value', opt.type)
            } else {
                // No other type cares about `value`, but doing this will
                // force a refresh of the label now that `ui.opts` has
                // been updated.
                uiInputTypeInput.typedInput('value',Date.now())
            }

            if(RED.editor.envVarList.debug) { console.log('envVarList: inputCellInput on:typedinputtypechange. ui.type = ' + ui.type) }
            switch (ui.type) {
                case 'input':
                    valueField.typedInput('types',ui.opts.types);
                    break;
                case 'select':
                    valueField.typedInput('types',['str']);
                    break;
                case 'checkbox':
                    valueField.typedInput('types',['bool']);
                    break;
                case 'spinner':
                    valueField.typedInput('types',['num']);
                    break;
                case 'cred':
                    valueField.typedInput('types',['cred']);
                    break;
                default:
                    valueField.typedInput('types', DEFAULT_ENV_TYPE_LIST);
            }
            if (ui.type === 'checkbox') {
                valueField.typedInput('type','bool');
            } else if (ui.type === 'spinner') {
                valueField.typedInput('type','num');
            }
            if (ui.type !== 'checkbox') {
                checkbox = null;
            }

        }).on("change", function(evt,type) {
            const selectedType = $(this).typedInput('type') // the UI typedInput type
            if(RED.editor.envVarList.debug) { console.log('envVarList: inputCellInput on:change. selectedType = ' + selectedType) }
            if (selectedType === 'conf-types') {
                const selectedConfigType = $(this).typedInput('value') || opt.type
                let activeWorkspace = RED.nodes.workspace(RED.workspaces.active());
                if (!activeWorkspace) {
                    activeWorkspace = RED.nodes.subflow(RED.workspaces.active());
                }

                // get a list of all config nodes matching the selectedValue
                const configNodes = [];
                RED.nodes.eachConfig(function(config) {
                    if (config.type == selectedConfigType && (!config.z || config.z === activeWorkspace.id)) {
                        const modulePath = config._def?.set?.id || ''
                        let label = RED.utils.getNodeLabel(config, config.id) || config.id;
                        label += config.d ? ' ['+RED._('workspace.disabled')+']' : '';
                        const _config = {
                            _type: selectedConfigType,
                            value: config.id,
                            label: label,
                            title: modulePath ? modulePath + ' - ' + label : label,
                            enabled: config.d !== true,
                            disabled: config.d === true,
                        }
                        configNodes.push(_config);
                    }
                });
                const tiTypes = {
                    value: selectedConfigType,
                    label: "config",
                    icon: "fa fa-cog",
                    options: configNodes,
                }
                valueField.typedInput('types', [tiTypes]);
                valueField.typedInput('type', selectedConfigType);
                valueField.typedInput('value', opt.value);


            } else if (ui.type === 'input') {
                var types = uiInputTypeInput.typedInput('value');
                ui.opts.types = (types === "") ? ["str"] : types.split(",");
                valueField.typedInput('types',ui.opts.types);
            }
        });
        valueField.on("change", function(evt) {
            if (checkbox) {
                checkbox.prop('checked',$(this).typedInput('value')==="true")
            }
        })
        // Set the input to the right type. This will trigger the 'typedinputtypechange'
        // event handler (just above ^^) to update the value if needed
        uiInputTypeInput.typedInput('type',ui.type)
    }

    function setLocale(l, list) {
        currentLocale = l;
        if (list) {
            var items = list.editableList("items");
            items.each(function (i, item) {
                var entry = $(this).data('data');
                var labelField = entry.ui.labelField;
                labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
                if (labelField.timeout) {
                    clearTimeout(labelField.timeout);
                    delete labelField.timeout;
                }
                labelField.addClass("input-updated");
                labelField.timeout = setTimeout(function() {
                    delete labelField.timeout
                    labelField.removeClass("input-updated");
                },3000);
            });
        }
    }

    /**
     * Lookup text for specific locale
     * @param labels - dict of labels
     * @param defaultLabel - fallback label if not found
     * @param locale - target locale
     * @returns {string} text for specified locale
     */
    function lookupLabel(labels, defaultLabel, locale) {
        if (labels) {
            if (labels[locale]) {
                return labels[locale];
            }
            if (locale) {
                var lang = locale.substring(0, 2);
                if (labels[lang]) {
                    return labels[lang];
                }
            }
        }
        return defaultLabel;
    }

    return {
        create: buildPropertiesList,
        setLocale: setLocale,
        lookupLabel: lookupLabel,
        DEFAULT_ENV_TYPE_LIST: DEFAULT_ENV_TYPE_LIST,
        DEFAULT_ENV_TYPE_LIST_INC_CRED: DEFAULT_ENV_TYPE_LIST_INC_CRED
    }
})();
