(function () {
    'use strict';

    /*
     * S10 Kanban Checklist Sync v3
     *
     * Синхронизирует с ACTIVE task_script:
     *
     * 1. изменение галочек;
     * 2. изменение текста пунктов;
     * 3. добавление новых пунктов;
     * 4. удаление пунктов.
     *
     * Интерфейс Kanban не изменяет.
     */

    if (window.__S10_KANBAN_SYNC_V3__) {
        return;
    }


    const urlParams =
        new URLSearchParams(
            window.location.search
        );


    const isKanbanFrame =
        urlParams.get('iframe') === '1' &&
        window.location.pathname.indexOf(
            '/pl/tasks/kanban/task-view'
        ) !== -1;


    if (!isKanbanFrame) {
        return;
    }


    window.__S10_KANBAN_SYNC_V3__ = true;


    function start() {

        if (!window.jQuery) {

            setTimeout(
                start,
                100
            );

            return;
        }


        const $ =
            window.jQuery;


        const taskId =
            new URLSearchParams(
                window.location.search
            ).get('id');


        if (!taskId) {

            console.warn(
                '[S10 Kanban Sync] taskId не найден'
            );

            return;
        }


        let timer =
            null;

        let lastContent =
            null;

        let version =
            0;

        let writing =
            false;


        /*
         * =================================
         * ACTIVE TASK SCRIPT
         * =================================
         */


        async function getActiveScriptId() {

            const response =
                await $.getJSON(
                    '/pl/tasks/task/task-scripts',
                    {
                        id: taskId
                    }
                );


            const html =
                response &&
                response.data &&
                response.data.html
                    ? response.data.html
                    : '';


            const doc =
                new DOMParser().parseFromString(
                    html,
                    'text/html'
                );


            const active =
                doc.querySelector(
                    '.active-task-script' +
                    '[data-task-script-id]'
                );


            return active
                ? active.getAttribute(
                    'data-task-script-id'
                )
                : null;
        }


        /*
         * =================================
         * CHECKLIST ACTIVE TASK SCRIPT
         * =================================
         */


        async function getChecklist(
            taskScriptId
        ) {

            const response =
                await $.getJSON(
                    '/pl/tasks/check-list/load-manual-view',
                    {
                        id: taskScriptId
                    }
                );


            const html =
                response &&
                response.html
                    ? response.html
                    : '';


            const doc =
                new DOMParser().parseFromString(
                    html,
                    'text/html'
                );


            const idInput =
                doc.querySelector(
                    'input[name="id"]'
                );


            const textarea =
                doc.querySelector(
                    'textarea[name="content"]'
                );


            return {

                id:
                    idInput &&
                    idInput.value
                        ? idInput.value
                        : '',

                content:
                    textarea
                        ? textarea.value.replace(
                            /\r\n/g,
                            '\n'
                        )
                        : ''
            };
        }


        /*
         * =================================
         * CONTENT ИЗ ЗАПРОСА GETCOURSE
         * =================================
         */


        function extractContent(data) {

            if (!data) {
                return null;
            }


            /*
             * application/x-www-form-urlencoded
             */
            if (
                typeof data === 'string'
            ) {

                try {

                    const request =
                        new URLSearchParams(
                            data
                        );


                    const content =
                        request.get(
                            'content'
                        );


                    return content === null
                        ? null
                        : content.replace(
                            /\r\n/g,
                            '\n'
                        );


                } catch (error) {

                    return null;
                }
            }


            /*
             * JS object.
             */
            if (
                typeof data === 'object' &&
                typeof data.content ===
                    'string'
            ) {

                return data.content.replace(
                    /\r\n/g,
                    '\n'
                );
            }


            return null;
        }


        /*
         * =================================
         * ЗАПИСЬ В ACTIVE CHECKLIST
         * =================================
         */


        async function syncToActive(
            currentVersion
        ) {

            if (
                writing ||
                lastContent === null ||
                currentVersion !== version
            ) {
                return;
            }


            const content =
                lastContent;


            try {

                const activeScriptId =
                    await getActiveScriptId();


                if (
                    !activeScriptId ||
                    currentVersion !== version
                ) {
                    return;
                }


                const checklist =
                    await getChecklist(
                        activeScriptId
                    );


                if (
                    currentVersion !== version
                ) {
                    return;
                }


                /*
                 * Уже совпадает —
                 * второй раз не записываем.
                 */
                if (
                    checklist.content ===
                    content
                ) {

                    console.log(
                        '[S10 Kanban Sync] уже совпадает:',
                        activeScriptId,
                        checklist.id
                    );

                    return;
                }


                writing =
                    true;


                /*
                 * Копируем последнюю версию
                 * Kanban в чек-лист ACTIVE task_script.
                 */
                const result =
                    await $.post(
                        '/pl/tasks/check-list/save',
                        {

                            task_script_id:
                                activeScriptId,

                            id:
                                checklist.id,

                            content:
                                content
                        }
                    );


                /*
                 * Проверяем результат
                 * непосредственно на сервере.
                 */
                const verification =
                    await getChecklist(
                        activeScriptId
                    );


                if (
                    verification.content ===
                    content
                ) {

                    console.log(
                        '[S10 Kanban Sync] ✓ синхронизировано:',
                        activeScriptId,
                        verification.id
                    );

                } else {

                    console.warn(
                        '[S10 Kanban Sync] сервер вернул другое состояние',
                        {
                            expected:
                                content,

                            actual:
                                verification.content,

                            result:
                                result
                        }
                    );
                }


            } catch (error) {

                console.error(
                    '[S10 Kanban Sync] ошибка:',
                    error
                );


            } finally {

                writing =
                    false;
            }
        }


        /*
         * =================================
         * СЛУШАЕМ СОХРАНЕНИЯ GETCOURSE
         * =================================
         */


        $(document)
            .off(
                'ajaxComplete.s10KanbanSyncV3'
            )
            .on(
                'ajaxComplete.s10KanbanSyncV3',

                function (
                    event,
                    xhr,
                    settings
                ) {

                    /*
                     * Не реагируем на POST,
                     * который делает сам наш код.
                     */
                    if (writing) {
                        return;
                    }


                    const url =
                        String(
                            settings &&
                            settings.url
                                ? settings.url
                                : ''
                        );


                    /*
                     * Галочки:
                     *
                     * /check-list/save-view
                     */
                    const isSaveView =
                        url.indexOf(
                            '/pl/tasks/check-list/save-view'
                        ) !== -1;


                    /*
                     * Редактирование:
                     *
                     * /check-list/save
                     *
                     * Важно отдельно исключаем save-view,
                     * потому что строка "/save"
                     * входит и в "/save-view".
                     */
                    const isFullSave =
                        !isSaveView &&
                        (
                            url.indexOf(
                                '/pl/tasks/check-list/save'
                            ) !== -1
                        );


                    if (
                        !isSaveView &&
                        !isFullSave
                    ) {
                        return;
                    }


                    const content =
                        extractContent(
                            settings.data
                        );


                    if (content === null) {

                        console.warn(
                            '[S10 Kanban Sync] ' +
                            'запрос сохранения пойман, ' +
                            'но content не найден',
                            url,
                            settings.data
                        );

                        return;
                    }


                    /*
                     * Запоминаем только
                     * самое последнее состояние.
                     */
                    lastContent =
                        content;


                    version++;


                    const currentVersion =
                        version;


                    clearTimeout(
                        timer
                    );


                    /*
                     * Штатное сохранение GetCourse
                     * уже завершилось.
                     *
                     * Небольшая задержка нужна,
                     * чтобы несколько быстрых изменений
                     * не создавали пачку POST-запросов.
                     */
                    timer =
                        setTimeout(
                            function () {

                                syncToActive(
                                    currentVersion
                                );

                            },
                            250
                        );


                    console.log(
                        '[S10 Kanban Sync] поймано:',
                        isSaveView
                            ? 'изменение галочек'
                            : 'редактирование пунктов',
                        content
                    );
                }
            );


        console.log(
            '[S10 Kanban Checklist Sync v3] запущен',
            taskId
        );
    }


    start();

})();