/**
 * @typedef {import ('/lib/js/ref-manager.js').RefManager} RefManager
 * @typedef {import('/lib/js/single-layer-manager.js').SingleLayerManager} SingleLayerManager
 * @typedef {import ('/lib/js/popup-manager.js').PopupManager} PopupManager
 * @typedef {import ('/lib/js/page-manager.js').PageManager} PageManager
 */

/**
 * Генерация функции для получения стилей маркера
 * @function
 * @param {Object<string, string>} marker_refs - объект с ссылками
 * @returns {((feature) => ol.style.Style)}
 */
const gen_get_style = recovery(
    marker_refs => feature => recovery(
        () => {
            /** Проверка feature */
            if (!feature || typeof feature.getProperties !== 'function') {
                throw new Error("Некорректный feature");
            }

            /** Свойства feature */
            const properties = feature.getProperties()

            /** Ссылка к иконке */
            const url = marker_refs[properties.type.toLowerCase()] 
                ?? marker_refs['археообъект'.toLowerCase()]

            /** Генерация стилей */
            return new ol.style.Style({
                image: new ol.style.Icon({
                    anchor: [0.5, 1],
                    scale: 0.08,
                    src: url
                })
            })
        },
        (...e) => {
            console.log("Ошибка при получении стилей (gen_get_style->get_style)");
            e.forEach(er => {throw er});
        }
    )(),
    (...e) => {
        console.log("Ошибка генерации функции стилей (gen_get_style)");
        e.forEach(er => {throw er});
    }
)

/**
 * Функция инициализирует карту
 * @function
 * @param {{coordinates: [number, number], target?: string}} arg
 * @returns {{map: ol.Map, layer: ol.layer.Vector}}
 */
const create_map_and_layer = ({coordinates, target = "map"}, style_f) => {
    /** Одиночный слой */
    let layer = new ol.layer.VectorImage({
        source: new ol.source.Vector({}),
        style: (feature) => style_f(feature)
    })

    /** Создание карты и её привязка к dom-элементу */
    const map = new ol.Map({
        view: new ol.View({
            center: ol.proj.fromLonLat(coordinates),
            zoom: 10,
            minZoom: 8
        }),
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM(),
            }),
            layer
        ],
        target: target
    })

    return {map, layer}
}

/** 
 * Активация стилей кнопки
 * @function
 */
const active = (btn) => btn.classList.replace('not-selected', 'selected')
/** 
 * Деактивация стилей кнопки
 * @function
 */
const deactive = (btn) => btn.classList.replace('selected', 'not-selected')

/** 
 * Функция инициализации главой страницы 
 * @function
 * @param {PageManager} page_manager
 * @param {RefManager} [previous_refs_manager] - менеджер ссылок предыдущей страницы
 */
const main_page_init = async ({page_manager}) => {
    /** 
     * Cоздание ссылок из загруженных фотографий
     * @function 
     * @returns {RefManager}
     */
    const icon_refs_manager_init = async () => {
        /** Данные (иконки) из внешнего json */
        const icons_data = (await get('json', './icons/icons.json'))
        const now_icons_data = {...icons_data.markers, ...icons_data.others}

        /** Менеджер иконок, заполненный ссылками */
        let icon_ref_manager = new RefManager()
        for (const [name, path] of Object.entries(now_icons_data))
            icon_ref_manager.save({
                key: name.toLowerCase(), 
                ref: URL.createObjectURL(await get('file', path))
            })

        return icon_ref_manager
    }

    /**
     * Создание и ининциализация карты
     * @function 
     * @param {RefManager} icon_ref_manager - менеджер ссылок
     * @returns {{map: ol.Map, layer: ol.layer.Vector}}
     */
    const map_init = (icon_refs_manager) =>
        create_map_and_layer(
            {
                coordinates: [70.008408, 60.001500],
                target: "map"
            }, 
            gen_get_style(icon_refs_manager.get_all())
        )

    /**
     * Создание и заполнение элемента с кнопками периодов
     * @function 
     * @param {Object} geojsons - объект, содержащий все geojson'ы
     */
    const periods_init = (geojsons, single_layer_manager) => {
        /** DOM-элемент, куда кнопки периодов загружаются */
        const time_select = document.getElementById('time-select')
        const periods = Object.keys(geojsons)
            .sort((a, b) =>  parseInt(a) -  parseInt(b))

        /** Массив кнопок с период-кнопками */
        const buttons_periods = periods.map(period => {
            /** Период-кнопка */
            const button = document.createElement('button')
            button.dataset.period = period;
            button.textContent = period;

            /** Добавление стилей: неактивная кнопка */
            button.classList.add('not-selected')

            /** Добавление в панель */
            time_select.appendChild(button)
            return button
        })

        /** Добавление слушателей (Загрузка geojson + сохранение состояния) */
        buttons_periods.forEach(bp => {
            bp.addEventListener('click', async () => {
                /** Изменение слоя на карте */
                single_layer_manager.set(geojsons[bp.dataset.period])

                /** Сохранение состояния */
                localStorage.setItem('selected', bp.dataset.period);

                /** Выключение всех остальных кнопок */
                buttons_periods.forEach(deactive)

                /** Включение текущей кнопки */
                active(bp)
            })
        })

        /** Загрузка последнего сохраненного статуса-периода (Имитация выбора) */
        const selected = localStorage.getItem('selected')
        const button_select = buttons_periods.find(bp => bp.dataset.period === selected);
        if (button_select) {
            button_select.click()
        } else
            buttons_periods[0].click()
    }

    /**
     * Создание и заполнение легенды (маркер - название)
     * @function
     * @param {RefManager} icon_refs_manager - менеджер ссылок
     */
    const legend_init = (icon_refs_manager) => {
        /** DOM-элемент легенды */
        const legend = document.getElementById('legend')

        for(const [name, ref] of Object.entries(icon_refs_manager.get_all())) {
            /** Row в легенде */
            const div = document.createElement('div')

            /** Иконка - маркер */
            const marker = document.createElement('img')

            /** Текст - название */
            const p = document.createElement('p');

            /** Помещение данных в row */
            marker.src = ref
            p.innerHTML = name

            /** Добавление в контейенер легенды */
            div.appendChild(marker)
            div.appendChild(p)
            legend.appendChild(div)
        }
    }

    /** 
     * Создание логотипов с переходом на другие страницы
     * @function 
     * @param {RefManager} icon_refs_manager - менеджер ссылок
     */
    const logos_init = (icon_refs_manager) => {
        /** DOM-элемент для логотипов */
        const logos = document.getElementById('logos')

        /**
         * Линковка ссылок на изображения и onclick'ов
         * @param {string} img_src 
         * @param {(() => {})} onclick 
         * @returns 
         */
        const logo_init = (img_src, onclick) => {
            /** Создание dom-элемента */
            const logo = document.createElement('img')
            /** Инъекция аргументов */
            logo.src = img_src
            logo.onclick = onclick

            return logo
        }

        /** Создание и добавление логотипов */
        [
            logo_init(
                icon_refs_manager.get('malaya_logo'),
                () => window.location.href = 'https://vk.com/anomalaya_rodina'
            ),
            logo_init(
                icon_refs_manager.get('rmc_logo'),
                () => window.location.href = 'https://vk.com/rcod_hmao'
            )
        ].forEach(logo => logos.appendChild(logo));
    }

    /** 
     * Инициализация popup-manager
     * @function
     * @param {ol.Map} map - ol-карта
     * @param {PageManager} page_manager - менеджер страниц
     * @param {RefManager} refs_manager - менеджер ссылок
     * @param {string} close_icon - икнонка крестика 
     * @returns {PopupManager}
     */
    const popup_manager_init = (map, page_manager, refs_manager, close_icon) => {
        /** Смещение popup */
        const offset = [0, 10]

        /** Контейнер popup  */
        const popup = document.getElementById('popup')
        
        /** Закрывашка, привязка ссылки иконки*/
        const popup_close = document.getElementById('popup-close')
        popup_close.src = close_icon

        /** Заголовок всплывающего окна */
        const popup_title = document.getElementById('popup-title')

        /** Контент всплывающего окна */
        const popup_content = document.getElementById('popup-content')

        /**
         * Поведение карты при нажатии на карту
         * @param {ol.Feature} feature - объект маркера
         */
        const map_on = feature => {
            /** Формирование контента */
            popup_title.innerHTML = feature.getProperties().name
            popup_content.innerHTML = ''

            /** Формирование кнопки 'подробнее' и его привязка */
            if (feature.getProperties().info_exist) {
                /** Создание ссылки 'подробнее' */
                const content_description = document.createElement('a')
                content_description.innerHTML = 'подробнее'
                content_description.href = '#'

                /** Привязка */
                popup_content.appendChild(content_description)

                /** Переход к info-page */
                content_description.onclick = () => 
                    page_manager.set_page('info-page', {
                        page_manager: page_manager, 
                        icon_refs_manager: refs_manager,
                        properties: feature.getProperties()
                    })
            }
        }

        return new PopupManager({
            map: map,
            popup_div: popup,
            popup_close: popup_close,
            offset: offset,
            map_on: map_on
        })
    }

    /** Защищенный вызов */
    await recovery(
        async () => {
            /** Получение всех иконок */
            const icon_ref_manager = await icon_refs_manager_init()
            
            /** Инициализация  */
            const {map, layer} = map_init(icon_ref_manager)
            const single_layer_manager = new SingleLayerManager(layer)

            /** Получение всех geojson'ов */
            const geojsons = await get_all_geojsons()

            periods_init(geojsons, single_layer_manager)

            legend_init(icon_ref_manager)
            logos_init(icon_ref_manager)

            popup_manager_init(map, page_manager, icon_ref_manager, icon_ref_manager.get('close'))
        },
        (...e) => {
            console.log("Ошибка при инициалиазции main-page");
            e.forEach(er => {throw er});
        }
    )()
}