"use strict";

const $categoryList = $('category-list');
let categoryConfig = {};
let hiddenRequiredFields = {};

/**
 * @param {string} category
 */
const addConfig = (category) => {
    if (category < 0) {
        idoit.Notify.error('No category has been selected.');
        return;
    }
    if ($categoryList.down('div#' + category)) {
        $categoryList.down('div#' + category).highlight();
        idoit.Notify.info('[{isys type="lang" ident="LC__SETTINGS__CMDB__VALIDATION__CATEGORY_HAS_ALREADY_BEEN_SELECTED"}]', {life:5});
        return;
    }
    
    setProperties(category);
};

/**
 * @param {JSON} data
 * @returns {*}
 */
const getIsVisible = (data) => {
    if (data.isNotHideable) {
        return new Element('span').update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_CANNOT_BE_HIDDEN"}]');
    }
    
    const title = data.isHidden
        ? '[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_HIDDEN"}]'
        : '[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_VISIBLE"}]';
    
    if ($editMode) {
       return new Element('button', { type: 'button', className: 'btn ' + (data.isHidden ? '' : 'pressed'), 'data-property-key': data.propertyKey})
           .update(new Element('img', { src: window.dir_images + 'axialis/user-interface/button-toggle-' + (data.isHidden ? 'off' : 'on') + '.svg', alt: '' }))
           .insert(new Element('span').update(title));
    }
    
    return new Element('span', { 'data-property-key': data.propertyKey }).update(title);
}

/**
 * @param {JSON} data
 * @returns {*}
 */
const getHideInOverview = (data) => {
    if (data.isNotHideable) {
        return new Element('span').update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_CANNOT_BE_HIDDEN"}]');
    }
    const $checkBox = new Element('input', {className: 'mr5', type: 'checkbox', 'data-property-key': data.propertyKey, checked: data.isHidden ? false : data.hideInOverview});
    
    if (!$editMode || data.isHidden) {
        $checkBox.disabled = true;
    }
    
    return new Element('div')
        .insert(new Element('label')
            .insert($checkBox)
            .insert(new Element('span').insert('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_CHECKBOX_HIDE_IN_OVERVIEW"}]'))
        );
}

/**
 * @param {string} category
 * @param {string} configurationKey
 * @param {string} keyToUpdate
 * @param {boolean} value
 */
const updateCategoryConfig = (category, configurationKey, keyToUpdate, value) => {
    for(let i = 0; i < categoryConfig[category]['properties'].length; i++) {
        if (categoryConfig[category]['properties'][i]['propertyKey'] === configurationKey) {
            categoryConfig[category]['properties'][i][keyToUpdate] = value;
            return;
        }
    }
};

/**
 * @param {string} category
 * @param {JSON} data
 * @returns {Element}
 */
const getRule = (category, data) => {
    const isVisible = getIsVisible(data);
    const hideInOverview = getHideInOverview(data);
    let hideIt = 0;

    const $row = new Element('div', {className: 'property-row', 'data-property': data.propertyKey})
        .insert(new Element('div', {className: 'property-label'}).update(new Element('strong').update(data.title)))
        .insert(new Element('div', {className:'property-option-is-visible'}).update(isVisible))
        .insert(new Element('div', {className:'property-option-hide-overview'}).update(hideInOverview));
    
    $row.on('click', 'button', (event) => {
        event.preventDefault();
        const $button = event.findElement('button').toggleClassName('pressed');

        const $checkbox = $button.up('div').next('.property-option-hide-overview').down('input');
        $checkbox.checked = false;
        
        if ($button.hasClassName('pressed')) {
            if (data.isRequired) {
                unregisterHiddenRequiredField(category, data.propertyKey);
            }
            $button
                .down('img').writeAttribute('src', window.dir_images + 'axialis/user-interface/button-toggle-on.svg')
                .next('span').update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_VISIBLE"}]');
            $checkbox.enable();
            hideIt = false;
        } else {
            if (data.isRequired) {
                registerHiddenRequiredField(category, data.propertyKey, event);
            }
            $button
                .down('img').writeAttribute('src', window.dir_images + 'axialis/user-interface/button-toggle-off.svg')
                .next('span').update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_HIDDEN"}]');
            $checkbox.disable();
            hideIt = true;
        }

        updateCategoryConfig(category, data.propertyKey, 'hideInOverview', false);
        updateCategoryConfig(category, data.propertyKey, 'isHidden', hideIt);
    });
    
    $row.on('click', 'input', function (event) {
        const $checkbox = event.findElement('input');
        const $propertyKey = $checkbox.readAttribute('data-property-key');
        
        if (data.isRequired) {
            if ($checkbox.checked) {
                registerHiddenRequiredField(category, data.propertyKey, event);
            } else {
                unregisterHiddenRequiredField(category, data.propertyKey);
            }
        }
        
        updateCategoryConfig(category, $propertyKey, 'hideInOverview', $checkbox.checked)
    });
    return $row;
};

/**
 * @param {string} category
 * @param {string} propertyKey
 */
const unregisterHiddenRequiredField = (category, propertyKey) => {
    if (hiddenRequiredFields[category]) {
        hiddenRequiredFields[category] = hiddenRequiredFields[category].filter((item) => {
            return item.propertyKey !== propertyKey;
        });
    }
};

/**
 * @param {string} category
 * @param {string} propertyKey
 * @param {object} event
 */
const registerHiddenRequiredField = (category, propertyKey, event) => {
    if (!hiddenRequiredFields[category]) {
        hiddenRequiredFields[category] = [];
    }

    const $categoryTitle = event.findElement().up('div.category-container').down('div.category-title').innerText;

    hiddenRequiredFields[category].push(
        {
            title: $categoryTitle + ': ' + event.findElement().up('div.property-row').down('div.property-label').innerText,
            propertyKey: propertyKey
        }
    );
};

/**
 * @param {JSON} data
 * @returns {JSON}
 */
const removeTitleFromData = (data) => {
    if (data['title']) {
        delete data['title'];
    }
    for(let i = 0; i < data['properties'].length; i++) {
        if (data['properties'][i]['title']) {
            delete data['properties'][i]['title'];
        }
    }

    return data;
};

/**
 * @param {string} category
 */
const setProperties = (category) => {
    new Ajax.Request(window.www_dir + 'system/ajaxAttributeVisibility/getProperties', {
        method:     'post',
        parameters: {
            id: category
        },
        onSuccess:  function (transport) {
            const json = transport.responseJSON;
            const data = json.data;
    
            addConfiguration(category, data);
        }
    });
};

/**
 * @param {string} category
 * @param {JSON} data
 */
const addConfiguration = (category, data) => {
    const title = data.title;
    const $toggleButton = new Element('button', { type: 'button', className: 'btn btn-secondary mr5 toggle', title: '[{isys type="lang" ident="LC__UNIVERSAL__TOGGLE_VIEW"}]', 'data-tooltip': 1 })
        .update(new Element('img', { src: window.dir_images + 'axialis/user-interface/angle-right-small.svg' }));
    let $closeButton = '';
    
    if ($editMode) {
        $closeButton = new Element('button', {type: 'button', className: 'btn ml-auto close', title: '[{isys type="lang" ident="LC__UNIVERSAL__REMOVE"}]', 'data-tooltip': 1 })
            .update(new Element('img', {src: window.dir_images + 'axialis/basic/symbol-cancel.svg', alt:'x'}));
    }
    
    $categoryList
        .insert(new Element('div', { id: category, className: 'border mt10 category-container' })
            .update(new Element('div', { className: 'category-header bg-neutral-200 p5 display-flex align-items-center' })
                .update($toggleButton)
                .insert(new Element('div', { className: 'fl category-title'}).update(title))
                .insert(new Element('div', { className: 'fl property-option-is-visible'}).update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_VISIBILITY"}]'))
                .insert(new Element('div', { className: 'fl property-option-hide-overview'}).update('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__LABEL_OVERVIEW_PAGE"}]'))
                .insert($closeButton)
            )
            .insert(new Element('div', { className:'border-top category-properties hide'})));
    const $attributesContent = new Element('div');
    
    data.properties.forEach(function (item) {
        $attributesContent.insert(getRule(category, item)).insert(new Element('hr'));
    });
    
    $(category).down('div.category-properties').update($attributesContent);
    categoryConfig[category] = removeTitleFromData(data);
    $('body').fire('update:tooltips');
};

/**
 * @param {JSON} config
 * @param {JSON} requiredFields
 * @param callback
 */
const saveConfig = (config, requiredFields, callback) => {
    new Ajax.Request(window.www_dir + 'system/ajaxAttributeVisibility/saveConfig', {
        method:     'post',
        parameters: {
            configuration: JSON.stringify(config),
            removeRequiredFields: JSON.stringify(requiredFields)
        },
        onSuccess:  function (transport) {
            var json = transport.responseJSON;
            
            if (!is_json_response(transport, true)) {
                return;
            }
            
            if (Object.isFunction(callback)) {
                callback(json);
            }
        }
    });
};

/**
 * @param {JSON} requiredFields
 * @returns {boolean}
 */
const confirmSave = (requiredFields) => {
    let $list = "\n\n";
    let $items = [];

    for(const item in requiredFields) {
        requiredFields[item].forEach((item) => {
            $items.push(item.title);
        });
    }
    
    if ($items.length > 0) {
        $items.map((item) => {
            $list += "- " + item + "\n";
        });
        
        $list += "\n";
        
        if (!confirm('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__MANDATORY_FIELD_QUESTION" p_bHtmlEncode=false}]'.replace('%s', $list))) {
            return false;
        }
    }
    return true;
};

$categoryList.on('click', 'button.toggle', (ev) => {
    var $toggleButton = ev.findElement('button.toggle'),
        $container = $toggleButton.up('.category-container').down('.category-properties').toggleClassName('hide');
    
    if ($container.hasClassName('hide')) {
        $toggleButton.down('img').writeAttribute('src', window.dir_images + 'axialis/user-interface/angle-right-small.svg');
    } else {
        $toggleButton.down('img').writeAttribute('src', window.dir_images + 'axialis/user-interface/angle-down-small.svg');
    }
});

// Remove a category configuration.
$categoryList.on('click', 'button.close', function (ev) {
    const $category = ev.findElement('button').up('.category-container').remove().id;
    delete categoryConfig[$category];
});

if ($('navbar_item_C__NAVMODE__SAVE')) {
    $('navbar_item_C__NAVMODE__SAVE').writeAttribute('onclick', false);

    $('navbar_item_C__NAVMODE__SAVE').on('click', function () {
        const $hiddenRequiredFieldsLength = Object.keys(hiddenRequiredFields).length;
        
        if ($hiddenRequiredFieldsLength) {
            let $list = "\n\n";
            let $items = [];

            for(const index in hiddenRequiredFields) {
                hiddenRequiredFields[index].forEach((item) => {
                    $items.push(item.title);
                });
            }

            if ($items.length > 0) {
                $list += $items.join("\n") + "\n\n";
    
                if (!confirm('[{isys type="lang" ident="LC__ATTRIBUTE_VISIBILITY__MANDATORY_FIELD_QUESTION" p_bHtmlEncode=false}]'.replace('%s', $list))) {
                    return false;
                }

                for(const index in hiddenRequiredFields) {
                    hiddenRequiredFields[index].forEach((item) => {
                        updateCategoryConfig(index, item.propertyKey, 'isRequired', false);
                    });
                }
            }
        }
        
        saveConfig(categoryConfig, hiddenRequiredFields, (json) => {
            if (json.success) {
                idoit.Notify.success('[{isys type="lang" ident="LC__INFOBOX__DATA_WAS_SAVED"}]');
            } else {
                idoit.Notify.error(json.message, {sticky: true});
            }
        });
    });
}