define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events'], function ($, Str, ModalFactory, ModalEvents){
    const PLUGIN = 'gradingform_kica';
    const NO_ZERO_GRADES = 0;
    const ONE_ZERO_GRADE = 1;
    const TOTAL_ZERO_GRADE = 2;

    let show_popup_from_mm = false;
    let show_popup_from_assign = false;

    return {
        init: function (){
            const KICA_INIT_GLOBAL_KEY = 'gradingform_kica_global_trigger_init';
            if (window[KICA_INIT_GLOBAL_KEY]) return;

            init_kica_rubrick_form();
            window[KICA_INIT_GLOBAL_KEY] = true;
        },
    };

    function init_kica_rubrick_form(){
        const MM_BODY_ID = 'page-blocks-ned_teacher_tools-marking_manager';
        const ASSIGN_BODY_ID = 'page-mod-assign-grader';

        switch(window.document.body.id){
            case MM_BODY_ID:
                init_mm_form(); break;
            case ASSIGN_BODY_ID:
                init_assign_form(); break;
            default:
                // if it is unknown page, set both events
                init_mm_form();
                init_assign_form();
        }
    }

    /**
     * Init page with kica form.
     */
    function init_mm_form(){
        let $form = get_kica_rubrick_form();
        if (empty($form)) return;

        const skip_submitter_names = ['cancel', 'reset', 'resetbutton', 'previous', 'next'];
        let clicked_ok = false;
        $form.on('submit', (e) => {
            if (show_popup_from_assign) return;
            if (clicked_ok){
                // use confirmation only ones
                clicked_ok = false;
                return;
            }

            let submitter = e.originalEvent.submitter;
            if (submitter){
                if ((submitter.name && skip_submitter_names.includes(submitter.name.toLowerCase())) ||
                    (submitter.value && skip_submitter_names.includes(submitter.value.toLowerCase()))) return;
            }

            show_popup_from_mm = false;
            let callback_ok = () => {
                show_popup_from_mm = true;
                clicked_ok = true;
                if (submitter){
                    $(submitter).trigger('click');
                } else {
                    $form.trigger('submit');
                }
            };
            if (popup_event(callback_ok)){
                e.preventDefault();
            }
        });
    }

    /**
     * Init assign grading page.
     */
    function init_assign_form(){
        const TRIGGER_TYPES_FOR_SAVE = ['save-changes', 'save-and-show-next'];
        const TRIGGER_TARGET_ELEMENT = window.document;
        const jquery_original_trigger = $.event.trigger;

        const check_save_trigger = function(args){
            if (empty(args)) return false;

            // jQuery.event.trigger(type, data, elem, onlyHandlers)
            let [type, , elem] = args;
            elem = elem || window.document;
            if (!type || elem !== TRIGGER_TARGET_ELEMENT) return false;

            return TRIGGER_TYPES_FOR_SAVE.includes(type);
        };

        $.event.trigger = function (...args){
            // show pop up or not
            if (!show_popup_from_mm && check_save_trigger(args)){
                show_popup_from_assign = false;
                let callback_ok = () => {
                    show_popup_from_assign = true;
                    jquery_original_trigger(...args);
                };
                if (popup_event(callback_ok)){
                    return undefined;
                }
            }
            return jquery_original_trigger(...args);
        };
    }

    /**
     * Get status of kica marks.
     * Always load and check status in real time, because kica marks can be changed in one script.
     *
     * @returns {number} status
     */
    function validate_marks(){
        let $form = get_kica_rubrick_form();
        if (empty($form)) return NO_ZERO_GRADES;

        const GRADES_SELECTOR = 'table#advancedgrading-criteria tr.criterion td.remark input.level-grade';
        let one_zero = false;
        let all_zeros = true;

        $form.find(GRADES_SELECTOR).each(function(){
            let value = empty(this.value) ? 0 : parseInt(this.value);
            if (value === 0){
                one_zero = true;
            } else {
                all_zeros = false
            }
        });

        if (all_zeros){
            return TOTAL_ZERO_GRADE;
        } else if (one_zero){
            return ONE_ZERO_GRADE;
        } else {
            return NO_ZERO_GRADES;
        }
    }

    /**
     * Create and show pop up.
     * @callback Callback
     *
     * @param {string} status     - status from validate_marks() function
     * @param {Callback} callback_ok
     */
    function show_warning_popup(status, callback_ok){
        ModalFactory.create({
            type: ModalFactory.types.SAVE_CANCEL,
            title: str('zero_grade_detected'),
            body: str(get_popup_body_str_key_by_status(status)),
            buttons: {
                'save': str('yes'),
                'cancel': str('no'),
            },
        }, undefined).then((modal) => {
            let $root = modal.getRoot();
            $root.on(ModalEvents.save, function (){
                if (callback_ok){
                    callback_ok();
                }
            });
            $root.keyup(function(e){
                if (e.key === 'Escape'){
                    $root.find('button[data-action="cancel"]').click();
                } else if (e.key === 'Enter'){
                    $root.find('button[data-action="save"]').click();
                }
            });
            modal.show();
        });
    }

    /**
     * @returns {*|jQuery|HTMLElement} kica form
     */
    function get_kica_rubrick_form(){
        return $('.gradingform form.gradeform');
    }

    /**
     * Process popup if necessary event was called.
     *
     * @callback callback
     * @param {callback} callback_ok
     *
     * @returns {boolean} true if pop up showed
     */
    function popup_event(callback_ok){
        let validate_status = validate_marks();
        if (validate_status > NO_ZERO_GRADES){
            show_warning_popup(validate_status, callback_ok);
            return true;
        }

        return false;
    }

    /**
     * Get pop up text body by kica marks status
     *
     * @param {int} status status type
     *
     * @returns {string}
     */
    function get_popup_body_str_key_by_status(status){
        switch (status){
            case ONE_ZERO_GRADE: return 'one_zero_grade';
            case TOTAL_ZERO_GRADE: return 'total_zero_grade';
            default: return '';
        }
    }

    /**
     * Check element for empty
     *
     * @param element
     *
     * @returns {boolean} true if empty
     */
    function empty(element){
        return !element || element.length === 0;
    }

    /**
     * Get string-translation promise
     *
     * @param {string} key - string key
     * @param {string} pl  - string plugin
     * @param {string|null} $a  - string parameters
     *
     * @returns {Promise}
     */
    function str(key, pl = PLUGIN, $a=null){
        return Str.get_string(key, pl, $a, '');
    }
});
