// settings_custom.js
var availableKeys = [];
var usedKeys = [];
var settingGroups = [];
var playlists = [];
var pattern = null;
var dependencyPatterns = []
var currentKey = "";
var currentSettingGroup = "";

$(document).ready(function () {
    if (customFormMode == "add" || customFormMode == "edit") {
        $("input[title*='Key']").bind("keyup", function () {
            ValidateKey();
        });
        $("input[title*='Key']").bind("focusout", function () {
            ValidateKey();
        });
        $("input[title*='Key']").bind("mousedown", function () {
            ValidateKey();
        });

        currentKey = $("input[title*='Key']").val();
        if (customFormMode == "edit") {
            // Edit mode
            $("input[title*='Key']").css("display", "none");
            $("input[title*='Key']").after(currentKey);
            $("textarea[title*='Value']").show();
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveSettingValues(currentKey) }, "sp.js");
        } else {
            // Add Mode
            $("input[id*='SaveItem']").prop("disabled", true);
            $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveAvailableKeys() }, "sp.js");
        }
    }
    else if (customFormMode == "listview") {
        //ExecuteOrDelayUntilScriptLoaded(function () { retrieveUsedDependencies() }, "sp.js");
    }

    // Breadcrum (no title) fix
    if (customFormMode == "edit") {
        $("span[id*='ContentMap'] a").each(function () {
            var linkText = $(this).html();
            if (linkText.indexOf("(") != -1 && linkText.indexOf(")") != -1) {
                $(this).html(currentKey);
            }
        });
    }
    else if (customFormMode == "display") {
        var tmpKey = $(".ms-formtable tbody td h3 a[name*='wsp_ucc_Key']").parent().parent().parent().children('td').eq(1).html();
        tmpKey = tmpKey.substring(tmpKey.indexOf("-->") + 3);
        tmpKey = tmpKey.replace(/^\s+|\s+$/gm, '');
        if (tmpKey != null && tmpKey != "") {
            $("span[id*='ContentMap'] span").each(function () {
                var linkText = $(this).html();
                if (linkText.indexOf("(") != -1 && linkText.indexOf(")") != -1) {
                    $(this).html(tmpKey);
                }
            });
        }
    }
});

// Setting Values Query
function retrieveSettingValues(filterValue) {
    try {
        var clientContext = SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle('SettingValues');

        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><Query><Where><And><Eq><FieldRef Name='Title' /><Value Type='Text'>" + filterValue + "</Value></Eq><Eq><FieldRef Name='wsp_ucc_sv_active' /><Value Type='Integer'>1</Value></Eq></And></Where></Query><OrderBy><FieldRef Name='Title' /></OrderBy><RowLimit>1</RowLimit></View>");
        this.collListItems = oList.getItems(camlQuery);

        clientContext.load(collListItems);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveSettingValuesSucceeded), Function.createDelegate(this, this.onQueryFailed));
    }
    catch (exp) {
        console.log("retrieveSettingValues error: " + exp);
    }
}

function onQueryRetrieveSettingValuesSucceeded(sender, args) {
    try {
        var listItemEnumerator = collListItems.getEnumerator();
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            var oListItemTitle = oListItem.get_item('Title');
            if (oListItemTitle == null) {
                oListItemTitle = "";
            }
            var oListItemType = oListItem.get_item('wsp_ucc_sv_type');
            if (oListItemType == null) {
                oListItemType = "";
            }
            var oListItemValue = oListItem.get_item('wsp_ucc_sv_value');
            if (oListItemValue == null) {
                oListItemValue = "";
            }
            var oListItemDefaultValue = oListItem.get_item('wsp_ucc_sv_default');
            if (oListItemDefaultValue == null) {
                oListItemDefaultValue = "";
            }
            var oListItemDescription = oListItem.get_item('wsp_ucc_sv_description');
            if (oListItemDescription == null) {
                oListItemDescription = "";
            }
            var oListItemScope = oListItem.get_item('wsp_ucc_sv_scope');
            if (oListItemScope == null) {
                oListItemScope = "";
            }
            var oListItemReadOnly = oListItem.get_item('wsp_ucc_sv_readonly');
            if (oListItemReadOnly == null) {
                oListItemReadOnly = "";
            }
            var oListItemSettingGroup = oListItem.get_item('wsp_ucc_sv_settinggroup');
            if (oListItemSettingGroup == null) {
                oListItemSettingGroup = "";
            }
            currentSettingGroup = oListItemSettingGroup;

            var selectedValue = $("textarea[title*='Value']").val();
            if (selectedValue == null) {
                selectedValue = "";
            }

            $("textarea[title='Description']").prop("disabled", false);
            $("select[title='Scope']").prop("disabled", false);
            if (oListItemReadOnly == false || (oListItemReadOnly == true && customFormMode == "add")) {
                $("textarea[title*='Value']").css("border", "1px solid #2a8dd4");
                if (oListItemType == "Dropdown") {
                    // Create dropdown
                    $(".main_booleanValue").remove();
                    $(".main_booleanLabel").remove();
                    CreateDropdown(oListItemValue, oListItemDefaultValue, selectedValue, "main", "textarea[title*='Value']", false);
                }
                else if (oListItemType == "Boolean") {
                    // Create boolean
                    $(".main_booleanValue").remove();
                    $(".main_booleanLabel").remove();
                    CreateBoolean(selectedValue, oListItemDefaultValue, "main", "textarea[title*='Value']", false);
                }
                else if (oListItemType == "RegEx") {
                    $("input[id*='SaveItem']").prop("disabled", true);
                    $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
                    $(".main_booleanValue").remove();
                    $(".main_booleanLabel").remove();
                    CreateSingleLine(selectedValue, oListItemDefaultValue, "main", "textarea[title*='Value']", false);
                    pattern = new RegExp(oListItemValue);
                    ValidateRegEx();
                    $("input[title*='Value']").bind("keyup", function () {
                        ValidateRegEx();
                    });
                    $("input[title*='Value']").bind("focusout", function () {
                        ValidateRegEx();
                    });
                    $("input[title*='Value']").bind("mousedown", function () {
                        ValidateRegEx();
                    });
                }
                else if (oListItemType == "MultiLine") {
                    $(".main_booleanValue").remove();
                    $(".main_booleanLabel").remove();
                    if (selectedValue == "") {
                        $("textarea[title*='Value']").val(oListItemDefaultValue);
                    }
                }
                else if (oListItemType == "Playlist") {
                    $(".main_booleanValue").remove();
                    $(".main_booleanLabel").remove();
                    ExecuteOrDelayUntilScriptLoaded(function () { retrievePlaylists(selectedValue, false) }, "sp.js");
                }

                // Set description field
                if (customFormMode == "add") {
                    $("textarea[title='Description']").val(oListItemDescription);
                    $("select[title='Scope']").val(oListItemScope);
                }

                //ExecuteOrDelayUntilScriptLoaded(function () { retrieveUsedDependencies() }, "sp.js");
            }
            else {
                $("textarea[title*='Value']").prop("disabled", true);
                $("textarea[title='Description']").prop("disabled", true);
                $("select[title='Scope']").prop("disabled", true);
                $("input[id*='SaveItem']").prop("disabled", true);
                $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
            }
        }
    }
    catch (exp) {
        console.log("onQueryRetrieveSettingValuesSucceeded " + exp);
    }
}

// Available Keys Query
function retrieveAvailableKeys() {
    var clientContext = SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle('SettingValues');

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><Query><Where><Eq><FieldRef Name='wsp_ucc_sv_active' /><Value Type='Integer'>1</Value></Eq></And></Where></Query><OrderBy><FieldRef Name='Title' /></OrderBy></View>");
    this.collAvailableKeysListItems = oList.getItems(camlQuery);

    clientContext.load(collAvailableKeysListItems);
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveAvailableKeysSucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQueryRetrieveAvailableKeysSucceeded(sender, args) {
    var listItemEnumerator = collAvailableKeysListItems.getEnumerator();
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        var oListItemTitle = oListItem.get_item('Title');
        availableKeys.push(oListItemTitle);
    }

    ExecuteOrDelayUntilScriptLoaded(function () { retrieveUsedKeys() }, "sp.js");
    $("input[title*='Key']").autocomplete({
        source: availableKeys,
        change: function (event, ui) {
            $(".main_booleanValue").remove();
            $(".main_booleanLabel").remove();
            $("#main_valueSL").remove();
            $("#main_valueDD").remove();
            $("textarea[title*='Value']").val("");
            $("textarea[title*='Value']").show();
            if ($("input[title*='Key']").val() != "") {
                ExecuteOrDelayUntilScriptLoaded(function () { retrieveSettingValues($("input[title*='Key']").val()) }, "sp.js");
                ValidateKey();
            }
        }
    });
}

// Used Keys Query
function retrieveUsedKeys() {
    var clientContext = SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle('Settings');

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml("<View><OrderBy><FieldRef Name='wsp_ucc_Key' /></OrderBy></View>");
    this.collUsedKeysListItems = oList.getItems(camlQuery);

    clientContext.load(collUsedKeysListItems);
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveUsedKeysSucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQueryRetrieveUsedKeysSucceeded(sender, args) {
    var listItemEnumerator = collUsedKeysListItems.getEnumerator();
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        var oListItemTitle = oListItem.get_item('wsp_ucc_Key');
        usedKeys.push(oListItemTitle.toLowerCase());
        var tmpIndex = $.inArray(oListItemTitle, availableKeys)
        if (tmpIndex != -1) {
            availableKeys.splice(tmpIndex, 1);
        }
    }
    ValidateKey();
}

// Setting Values Dependencies Query
function retrieveDependencies() {
    try {
        if (currentSettingGroup != "") {
            var clientContext = SP.ClientContext.get_current();
            var oList = clientContext.get_web().get_lists().getByTitle('SettingValues');

            var camlQuery = new SP.CamlQuery();
            camlQuery.set_viewXml("<View><Query><Where><And><Neq><FieldRef Name='Title' /><Value Type='Text'>" + currentKey + "</Value></Neq><And><Eq><FieldRef Name='wsp_ucc_sv_settinggroup' /><Value Type='Text'>" + currentSettingGroup + "</Value></Eq><Eq><FieldRef Name='wsp_ucc_sv_active' /><Value Type='Integer'>1</Value></Eq></And></And></Where></Query><OrderBy><FieldRef Name='Title' /></OrderBy></View>");
            this.collDependencyListItems = oList.getItems(camlQuery);

            clientContext.load(collDependencyListItems, "Include(Title,wsp_ucc_sv_description,wsp_ucc_sv_scope,wsp_ucc_sv_type,wsp_ucc_sv_default,wsp_ucc_sv_value)");
            clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveDependenciesSucceeded), Function.createDelegate(this, this.onQueryFailed));
        }
    }
    catch (exp) {
        console.log("retrieveDependencies " + exp);
    }
}

function onQueryRetrieveDependenciesSucceeded(sender, args) {
    try {
        var listItemEnumerator = collDependencyListItems.getEnumerator();
        $(".dependencieRows").remove();
        var outputHtml = "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr><b>Dependencies</b></nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>&nbsp;</td></tr>";
        var outputHtml1 = "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr><i>Already added</i></nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>&nbsp;</td></tr>";
        var outputHtml2 = "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr><i>Not added</i></nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>&nbsp;</td></tr>";
        var seperator = "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr></nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>&nbsp;</td></tr>";
        var prefixes_boolean = [];
        var prefixes_dropdown = [];
        var prefixes_regex = [];
        var prefixes_playlist = [];
        var counter1 = 0;
        var counter2 = 0;
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            var oListItemTitle = oListItem.get_item('Title');
            var oListItemDescription = oListItem.get_item('wsp_ucc_sv_description');
            var oListItemScope = oListItem.get_item('wsp_ucc_sv_scope');
            var oListItemType = oListItem.get_item('wsp_ucc_sv_type');
            var oListItemDefault = oListItem.get_item('wsp_ucc_sv_default');
            var oListItemValue = oListItem.get_item('wsp_ucc_sv_value');
            var inputColumn = "";
            var selectedValue = "";
            var usedKey = oListItemTitle.toLowerCase();
            var usedSetting = false;
            if (usedKey in usedKeys != false) {
                selectedValue = usedKeys[usedKey][1];
                oListItemDefault = selectedValue;
                oListItemDescription = usedKeys[usedKey][2];
                oListItemScope = usedKeys[usedKey][3];
                usedSetting = true;
            }

            if (oListItemType == "Dropdown") {
                inputColumn = "<input type='hidden' id='dinput_" + oListItemTitle + "' data-valid='true' value='" + oListItemDefault + "'>" + CreateDropdown(oListItemValue, oListItemDefault, selectedValue, oListItemTitle, "#dinput_" + oListItemTitle, true);
                prefixes_dropdown.push(oListItemTitle);
            }
            else if (oListItemType == "Boolean") {
                inputColumn = "<input type='hidden' id='dinput_" + oListItemTitle + "' data-valid='true' value='" + oListItemDefault + "'>" + CreateBoolean(selectedValue, oListItemDefault, oListItemTitle, "#dinput_" + oListItemTitle, true);
                prefixes_boolean.push(oListItemTitle);
            }
            else if (oListItemType == "RegEx") {
                if (oListItemDefault == null) {
                    oListItemDefault = "";
                }
                inputColumn = "<input type='text' id='dinput_" + oListItemTitle + "' style='width: 300px;' data-pattern=\"" + oListItemValue + "\" data-valid='false' value='" + oListItemDefault + "'>";
                prefixes_regex.push(oListItemTitle);
            }
            else if (oListItemType == "Playlist") {
                if (oListItemDefault == null) {
                    oListItemDefault = playlists[0];
                }
                inputColumn = "<input type='hidden' id='dinput_" + oListItemTitle + "' data-valid='true' value='" + oListItemDefault + "'>" + CreatePlaylistDropdown(playlists, selectedValue, oListItemTitle, "#dinput_" + oListItemTitle, true);
                prefixes_playlist.push(oListItemTitle);
            }

            if (usedSetting == true) {
                counter1++;
                inputColumn += "<a href='#' id='btnsave_" + oListItemTitle + "' class='BtnSaveDependency' style='float: right;' data-key='" + oListItemTitle + "' data-description='" + oListItemDescription + "' data-scope='" + oListItemScope + "' data-mode='update'>Update</a>";
                outputHtml1 += "<tr class='dependencieRows'><td id='dlabel_" + oListItemTitle + "' nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr>" + oListItemTitle + "</nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>" + inputColumn + "</td></tr>";
            }
            else {
                counter2++;
                inputColumn += "<a href='#' id='btnsave_" + oListItemTitle + "' class='BtnSaveDependency' style='float: right;' data-key='" + oListItemTitle + "' data-description='" + oListItemDescription + "' data-scope='" + oListItemScope + "' data-mode='add'>Add</a>";
                outputHtml2 += "<tr class='dependencieRows'><td id='dlabel_" + oListItemTitle + "' nowrap='true' valign='top' width='113px' class='ms-formlabel'><h3 class='ms-standardheader'><nobr>" + oListItemTitle + "</nobr></h3></td><td valign='top' width='350px' class='ms-formbody'>" + inputColumn + "</td></tr>";
            }
        }

        outputHtml1 += "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'>&nbsp;</td><td valign='top' width='350px' class='ms-formbody'><a href='#' id='btnupdateall' style='float: right;'>Update All</a></td></tr>";
        outputHtml2 += "<tr class='dependencieRows'><td nowrap='true' valign='top' width='113px' class='ms-formlabel'>&nbsp;</td><td valign='top' width='350px' class='ms-formbody'><a href='#' id='btnaddall' style='float: right;'>Add All</a></td></tr>";
        if (counter1 > 0) {
            outputHtml += outputHtml1 + seperator;
        }
        if (counter2 > 0) {
            if (counter1 > 0) {
                outputHtml += seperator;
            }
            outputHtml += outputHtml2 + seperator;
        }
        $("select[title*='Scope']").closest("tr").after(outputHtml);

        $("#btnupdateall").click(function () {
            $(".BtnSaveDependency").each(function () {
                var mode = $(this).attr("data-mode");
                if (mode == "update") {
                    var key = $(this).attr("data-key");
                    var valid = $("#dinput_" + key).attr("data-valid");
                    if (valid == "true") {
                        var data = []
                        data.push(key);
                        data.push($("#dinput_" + key).val());
                        data.push($(this).attr("data-description"));
                        data.push($(this).attr("data-scope"));
                        createDependencyItem(data);
                    }
                }
            });
        });

        $("#btnaddall").click(function () {
            $(".BtnSaveDependency").each(function () {
                var mode = $(this).attr("data-mode");
                if (mode == "add") {
                    var key = $(this).attr("data-key");
                    var valid = $("#dinput_" + key).attr("data-valid");
                    if (valid == "true") {
                        var data = []
                        data.push(key);
                        data.push($("#dinput_" + key).val());
                        data.push($(this).attr("data-description"));
                        data.push($(this).attr("data-scope"));
                        createDependencyItem(data);
                    }
                }
            });
        });

        $(".BtnSaveDependency").click(function () {
            var key = $(this).attr("data-key");
            var valid = $("#dinput_" + key).attr("data-valid");
            if (valid == "true") {
                var data = []
                data.push(key);
                data.push($("#dinput_" + key).val());
                data.push($(this).attr("data-description"));
                data.push($(this).attr("data-scope"));
                createDependencyItem(data);
            }
        });

        // Set boolean click events
        for (var i in prefixes_boolean) {
            $("." + prefixes_boolean[i] + "_booleanValue").click(function () {
                var tmpPrefix = $(this).attr("id");
                tmpPrefix = tmpPrefix.substring(0, tmpPrefix.indexOf("_"));
                SetBooleanValue($(this), "#dinput_" + tmpPrefix);
            });
        }

        // Set dropdown change events
        for (var i in prefixes_dropdown) {
            $("#" + prefixes_dropdown[i] + "_valueDD").css("width", "311px");
            $("#" + prefixes_dropdown[i] + "_valueDD").change(function () {
                var tmpPrefix = $(this).attr("id");
                tmpPrefix = tmpPrefix.substring(0, tmpPrefix.indexOf("_"));
                $("#dinput_" + tmpPrefix).val($(this).val());
            });
        }

        // Set regex change events
        for (var i in prefixes_regex) {
            var element = "#dinput_" + prefixes_regex[i];
            var tmpPrefix = prefixes_regex[i];
            var patternString = $(element).attr("data-pattern");
            if (patternString == "null") {
                patternString = "";
            }
            var newPattern = new RegExp(patternString);
            var patternExists = tmpPrefix in dependencyPatterns;
            if (patternExists == false) {
                dependencyPatterns[tmpPrefix] = newPattern;
            }

            ValidateDependencyRegEx(element, newPattern);
            $(element).bind("keyup", function () {
                var tmpPrefix = $(this).attr("id");
                var element = "#" + tmpPrefix;
                tmpPrefix = tmpPrefix.substring(tmpPrefix.indexOf("_") + 1);
                ValidateDependencyRegEx(element, dependencyPatterns[tmpPrefix]);
            });
            $(element).bind("focusout", function () {
                var tmpPrefix = $(this).attr("id");
                var element = "#" + tmpPrefix;
                tmpPrefix = tmpPrefix.substring(tmpPrefix.indexOf("_") + 1);
                ValidateDependencyRegEx(element, dependencyPatterns[tmpPrefix]);
            });
            $(element).bind("mousedown", function () {
                var tmpPrefix = $(this).attr("id");
                var element = "#" + tmpPrefix;
                tmpPrefix = tmpPrefix.substring(tmpPrefix.indexOf("_") + 1);
                ValidateDependencyRegEx(element, dependencyPatterns[tmpPrefix]);
            });
        }

        // Set playlist change events
        for (var i in prefixes_playlist) {
            $("#" + prefixes_playlist[i] + "_valueDD").css("width", "311px");
            $("#" + prefixes_playlist[i] + "_valueDD").change(function () {
                var tmpPrefix = $(this).attr("id");
                tmpPrefix = tmpPrefix.substring(0, tmpPrefix.indexOf("_"));
                $("#dinput_" + tmpPrefix).val($(this).val());
            });
        }
    }
    catch (exp) {
        console.log("onQueryRetrieveDependenciesSucceeded " + exp);
    }
}

// Save dependency setting
function createDependencyItem(data) {
    try {
        SP.UI.Status.removeAllStatus(true);
        var clientContext = SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle('Settings');
        var oListItem = null;

        var key = data[0];
        var key_lower = key.toLowerCase();
        var itemStatus = "";
        if (key_lower in usedKeys == false) {
            var itemCreateInfo = new SP.ListItemCreationInformation();
            oListItem = oList.addItem(itemCreateInfo);
            oListItem.set_item('wsp_ucc_Key', data[0]);
            itemStatus = "added";
        } else {
            var itemId = usedKeys[key_lower][0];
            oListItem = oList.getItemById(itemId);
            itemStatus = "updated";
        }

        oListItem.set_item('wsp_ucc_Value', data[1]);
        oListItem.set_item('wsp_ucc_Description', data[2]);
        oListItem.set_item('wsp_ucc_scope', data[3]);
        oListItem.update();

        clientContext.load(oListItem);
        clientContext.executeQueryAsync(Function.createDelegate(this, function () { onQueryCreateDependencyItemSucceeded(oListItem, itemStatus); }), Function.createDelegate(this, this.onQueryFailed));
    }
    catch (exp) {
        console.log("createDependencyItem " + exp);
    }
}

function onQueryCreateDependencyItemSucceeded(updatedItem, itemStatus) {
    try {
        var id = updatedItem.get_id();
        var key = updatedItem.get_item('wsp_ucc_Key');
        var value = updatedItem.get_item('wsp_ucc_Value');
        var description = updatedItem.get_item('wsp_ucc_Description');
        var scope = updatedItem.get_item('wsp_ucc_scope');
        var labelKey = key;
        key = key.toLowerCase();
        usedKeys[key] = [];
        usedKeys[key].push(id);
        usedKeys[key].push(value);
        usedKeys[key].push(description);
        usedKeys[key].push(scope);
        console.log("Item " + itemStatus + ": " + id);

        if (itemStatus == "added") {
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveDependencies() }, "sp.js");
        }
    }
    catch (exp) {
        console.log("onQueryCreateDependencyItemSucceeded " + exp);
    }
}

// Setting Used Dependencies Query
function retrieveUsedDependencies() {
    try {
        var clientContext = SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle('Settings');

        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><OrderBy><FieldRef Name='wsp_ucc_Key' /></OrderBy></View>");
        this.collUsedListItems = oList.getItems(camlQuery);

        clientContext.load(collUsedListItems);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveUsedDependenciesSucceeded), Function.createDelegate(this, this.onQueryFailed));
    }
    catch (exp) {
        console.log("retrieveUsedDependencies " + exp);
    }
}

function onQueryRetrieveUsedDependenciesSucceeded(sender, args) {
    try {
        var listItemEnumerator = collUsedListItems.getEnumerator();
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            var oListItemId = oListItem.get_id();
            var oListItemTitle = oListItem.get_item('wsp_ucc_Key');
            var oListItemValue = oListItem.get_item('wsp_ucc_Value');
            var oListItemDescription = oListItem.get_item('wsp_ucc_Description');
            var oListItemScope = oListItem.get_item('wsp_ucc_scope');
            oListItemTitle = oListItemTitle.toLowerCase();
            usedKeys[oListItemTitle] = [];
            usedKeys[oListItemTitle].push(oListItemId);
            usedKeys[oListItemTitle].push(oListItemValue);
            usedKeys[oListItemTitle].push(oListItemDescription);
            usedKeys[oListItemTitle].push(oListItemScope);
        }

        if (customFormMode == "listview") {
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveAllDependencies() }, "sp.js");
        }
        else {
            ExecuteOrDelayUntilScriptLoaded(function () { retrievePlaylists("", true) }, "sp.js");
        }
    }
    catch (exp) {
        console.log("onQueryRetrieveUsedDependenciesSucceeded " + exp);
    }
}

// Setting Values All Dependencies Query
function retrieveAllDependencies() {
    try {
        var clientContext = SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle('SettingValues');

        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><Query><Where><Eq><FieldRef Name='wsp_ucc_sv_active' /><Value Type='Integer'>1</Value></Eq></Where></Query><OrderBy><FieldRef Name='Title' /></OrderBy></View>");
        this.collAllDependencyListItems = oList.getItems(camlQuery);

        clientContext.load(collAllDependencyListItems);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrieveAllDependenciesSucceeded), Function.createDelegate(this, this.onQueryFailed));
    }
    catch (exp) {
        console.log("retrieveAllDependencies " + exp);
    }
}

function onQueryRetrieveAllDependenciesSucceeded(sender, args) {
    try {
        var listItemEnumerator = collAllDependencyListItems.getEnumerator();
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            var oListItemTitle = oListItem.get_item('Title');
            var oListItemSettingGroup = oListItem.get_item('wsp_ucc_sv_settinggroup');

            var keyExists = oListItemSettingGroup in settingGroups;
            if (keyExists == false) {
                settingGroups[oListItemSettingGroup] = [];
                settingGroups[oListItemSettingGroup].push(oListItemTitle);
            }
            else {
                settingGroups[oListItemSettingGroup].push(oListItemTitle);
            }
        }

        var usedGroups = [];
        $(".ms-vb2").closest("tr").find("td:eq(1)").each(function () {
            var key = $(this).html();
            for (var group in settingGroups) {
                if (group != "null" && $.inArray(group, usedGroups) == -1) {
                    if ($.inArray(key, settingGroups[group]) != -1) {
                        var groupOk = true;
                        var noticeItems = "";
                        for (var i in settingGroups[group]) {
                            var value = settingGroups[group][i];
                            if (value != key) {
                                if (value.toLowerCase() in usedKeys == false) {
                                    groupOk = false;
                                    if (noticeItems == "") {
                                        noticeItems += value;
                                    }
                                    else {
                                        noticeItems += ", " + value;
                                    }
                                }
                            }
                        }

                        if (groupOk == false) {
                            var outputHtml = "<span class='notice' title='Not all related settings are added to list: " + noticeItems + "'>&nbsp;</span>";
                            $(this).html(key + outputHtml);
                        }
                        usedGroups.push(group);
                    }
                }
            }
        });
    }
    catch (exp) {
        console.log("onQueryRetrieveAllDependenciesSucceeded " + exp);
    }
}

// Playlists query
function retrievePlaylists(selectedPlaylist, usedForDependency) {
    try {
        var clientContext = SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle('Playlists');

        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><OrderBy><FieldRef Name='Title' /></OrderBy></View>");
        this.collPlaylistItems = oList.getItems(camlQuery);
        this.selectedPlaylist = selectedPlaylist;
        this.usedForDependency = usedForDependency;

        clientContext.load(collPlaylistItems);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQueryRetrievePlaylistsSucceeded), Function.createDelegate(this, this.onQueryFailed));
    }
    catch (exp) {
        console.log("retrievePlaylists " + exp);
    }
}

function onQueryRetrievePlaylistsSucceeded(sender, args) {
    try {
        playlists = [];
        var listItemEnumerator = collPlaylistItems.getEnumerator();
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            var oListItemTitle = oListItem.get_item('Title');

            var keyExists = $.inArray(oListItemTitle, playlists);
            if (keyExists == -1) {
                playlists.push(oListItemTitle);
            }
        }

        if (usedForDependency == false) {
            CreatePlaylistDropdown(playlists, selectedPlaylist, "main", "textarea[title*='Value']", false);
        }
        else {
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveDependencies() }, "sp.js");
        }
    }
    catch (exp) {
        console.log("onQueryRetrievePlaylistsSucceeded " + exp);
    }
}

function onQueryFailed(sender, args) {
    console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

function CreateDropdown(textValue, defaultValue, selectedValue, prefix, element, output) {
    $("#" + prefix + "_valueDD").remove();
    var outputHtml = "";

    if (textValue != null && textValue != "") {
        var counter = 0;
        outputHtml = '<select id="' + prefix + '_valueDD" class="ms-long ms-spellcheck-true">';
        if (textValue.indexOf(';') != -1) {
            var textValueSplit = textValue.split(";");
            textValueSplit.sort();
            for (j = 0; j < textValueSplit.length; j++) {
                counter++;
                var tmpValue = textValueSplit[j];
                if (selectedValue != "" && selectedValue == tmpValue) {
                    outputHtml += '<option value="' + tmpValue + '" selected>' + tmpValue + '</option>'
                }
                else if (selectedValue == "" && defaultValue == tmpValue) {
                    outputHtml += '<option value="' + tmpValue + '" selected>' + tmpValue + '</option>'
                }
                else {
                    outputHtml += '<option value="' + tmpValue + '">' + tmpValue + '</option>'
                }
            }
        }
        else {
            counter++;
            outputHtml += '<option value="' + textValue + '" selected>' + textValue + '</option>'
        }

        outputHtml += '</select>';

        if (counter > 0) {
            if (output == false) {
                $(element).hide();
                $(element).after(outputHtml);

                $(element).val($("#" + prefix + "_valueDD").val());
                $("#" + prefix + "_valueDD").change(function () {
                    $(element).val($(this).val());
                });
            }
            else {
                return outputHtml;
            }
        }
    }
}

function CreateSingleLine(textValue, defaultValue, prefix, element, output) {
    $("#" + prefix + "_valueSL").remove();
    var outputHtml = "";

    var elementValue = defaultValue;
    if (textValue != null && textValue != "") {
        elementValue = textValue;
    }

    outputHtml = '<input type="text" id="' + prefix + '_valueSL" title="Value Required Field" value="' + elementValue + '" class="ms-long ms-spellcheck-true">';
    if (output == false) {
        $(element).hide();
        $(element).after(outputHtml);
        $(element).val($("#" + prefix + "_valueSL").val());
        $("#" + prefix + "_valueSL").change(function () {
            $(element).val($(this).val());
        });
    }
    else {
        return outputHtml;
    }
}

function CreatePlaylistDropdown(itemArray, selectedValue, prefix, element, output) {
    $("#" + prefix + "_valueDD").remove();
    var outputHtml = "";

    if (itemArray != null && itemArray.length > 0) {
        var counter = 0;
        outputHtml = '<select id="' + prefix + '_valueDD" class="ms-long ms-spellcheck-true">';
        for (j = 0; j < itemArray.length; j++) {
            counter++;
            var tmpValue = itemArray[j];
            if (selectedValue != "" && selectedValue == tmpValue) {
                outputHtml += '<option value="' + tmpValue + '" selected>' + tmpValue + '</option>'
            }
            else {
                outputHtml += '<option value="' + tmpValue + '">' + tmpValue + '</option>'
            }
        }
        outputHtml += '</select>';

        if (counter > 0) {
            if (output == false) {
                $(element).hide();
                $(element).after(outputHtml);

                $(element).val($("#" + prefix + "_valueDD").val());
                $("#" + prefix + "_valueDD").change(function () {
                    $(element).val($(this).val());
                });
            }
            else {
                return outputHtml;
            }
        }
    }
    else {
        if (output == true) {
            return outputHtml;
        }
    }
}

function CreateBoolean(selectedValue, defaultValue, prefix, element, output) {
    var outputHtml = "";
    var checked1 = "";
    var checked2 = "";
    if (selectedValue != "") {
        if (selectedValue.toLowerCase() == "true") {
            checked1 = " checked='checked'";
        }
        else if (selectedValue.toLowerCase() == "false") {
            checked2 = " checked='checked'";
        }
    }
    else if (selectedValue == "" && defaultValue != "") {
        if (defaultValue.toLowerCase() == "true") {
            checked1 = " checked='checked'";
            $(element).val("true");
        }
        else if (defaultValue.toLowerCase() == "false") {
            checked2 = " checked='checked'";
            $(element).val("false");
        }
    }

    var booleanElement1 = "<input type='radio' id='" + prefix + "_boolValue1' name='" + prefix + "_booleanValue' class='" + prefix + "_booleanValue' value='true'" + checked1 + "><label class='" + prefix + "_booleanLabel'>True</label>";
    var booleanElement2 = "<input type='radio' id='" + prefix + "_boolValue2' name='" + prefix + "_booleanValue' class='" + prefix + "_booleanValue' value='false'" + checked2 + "><label class='" + prefix + "_booleanLabel'>False</label>";
    outputHtml = booleanElement1 + " " + booleanElement2;

    if (output == false) {
        $(element).hide();
        $(element).after(outputHtml);

        $("." + prefix + "_booleanValue").click(function () {
            SetBooleanValue($(this), element);
        });
    }
    else {
        return outputHtml;
    }
}

function SetBooleanValue(element, targetElement) {
    var booleanValue = $(element).val();
    $(targetElement).val(booleanValue);
}

function ValidateRegEx() {
    $("input[title*='Value']").css("border", "1px solid red");
    $("input[id*='SaveItem']").prop("disabled", true);
    $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
    var testValue = $("input[title*='Value']").val();
    if (pattern.test(testValue) == true) {
        $("input[id*='SaveItem']").prop("disabled", false);
        $("input[title*='Value']").css("border", "1px solid green");
        $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large");
    }
}

function ValidateDependencyRegEx(element, testPattern) {
    var prefix = element.substring(1, element.indexOf("_"));
    var saveButtonElement = element.replace(prefix, "btnsave");
    $(element).css("border", "1px solid red");
    $(element).attr("data-valid", "false");
    $(saveButtonElement).hide();
    var testValue = $(element).val();
    if (testPattern.test(testValue) == true) {
        $(element).css("border", "1px solid green");
        $(element).attr("data-valid", "true");
        $(saveButtonElement).show();
    }
}

function ValidateKey() {
    var testValue = $("input[title*='Key']").val();
    if (testValue != null && testValue != "") {
        if (customFormMode == "add") {
            $("input[title*='Key']").css("border", "1px solid red");
            $("input[id*='SaveItem']").prop("disabled", true);
            $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
            if ($.inArray(testValue.toLowerCase(), usedKeys) == -1) {
                $("input[id*='SaveItem']").prop("disabled", false);
                $("input[title*='Key']").css("border", "1px solid green");
                $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large");
            }
            ExecuteOrDelayUntilScriptLoaded(function () { retrieveSettingValues($("input[title*='Key']").val()) }, "sp.js");
        }
    }
    else {
        $("input[title*='Key']").css("border", "1px solid red");
        $("input[id*='SaveItem']").prop("disabled", true);
        $("a[id='Ribbon.ListForm.Edit.Commit.Publish-Large']").prop("class", "ms-cui-ctl-large ms-cui-disabled");
    }
}