/*
 * This file is a part of the LinkAhead Project.
 *
 * Copyright (C) 2021-2024 IndiScale GmbH <info@indiscale.com>
 * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
 * Copyright (C) 2023 Florian Spreckelsen <f.spreckelsen@indiscale.com>
 * Copyright (C) 2023 Daniel Hornung <d.hornung@indiscale.com>
 * Copyright (C) 2024 Joscha Schmiedt <joscha@schmiedt.dev>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

"use strict";

/**
 * Cosmetics module is a collection of small look-and-feel tweaks for the
 * LinkAhead webui.
 *
 * @author Timm Fitschen
 */
var cosmetics = new function () {

    /**
     * Cut-off length of links. When linkify processes the links any href
     * longer than this will be cut off at the end and "[...]" will be
     * appended for the link text.
     */
    var _link_cut_off_length = 40;

    var _custom_datetime = function () {
        $('.caosdb-f-property-datetime-value').each(function (index) {
            if (!($(this).hasClass("caosdb-v-property-datetime-customized"))) {
                var result = this.innerText.replace(/T/, " ").replace(/\+.*/, "");
                result = `<span class="caosdb-v-property-datetime-customized-newvalue">${result}</span>`;

                // add class to highlight that this has been customized already
                $(this).addClass("caosdb-v-property-datetime-customized")
                $(this).hide();
                $(this).after(result);
            }
        });
    }

    /**
     * Remove all the custom datetime elements again, for example when entering the edit mode.
     */
    var _custom_datetime_clear = function () {
        $('.caosdb-v-property-datetime-customized-newvalue').each(function () {
            $(this).remove();
        }
        )
    }

    /**
     * Return a string with all occurences of a http(s) url in a given string replaced by <a> elements
     * @param {string} text - The text to be searched for URLs
     * @returns {string} text with <a> elements instead of raw links
     */
    function linkify_string(text) {
        // const match_url_regex = /https?:\/\/[^\s]*/g // original
        // https://regexr.com helps you design regex
        const match_url_regex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.?[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g

        return text.replace(match_url_regex, function (href) {
            var link_text = href;
            if (_link_cut_off_length > 4 && link_text.length > _link_cut_off_length) {
                link_text = link_text.substring(0, _link_cut_off_length - 5) + "[...]";
            }

            return `<a title="Open ${href} in a new tab." target="_blank" class="caosdb-v-property-href-value" href="${href}">${link_text} <i class="bi bi-box-arrow-up-right"></i></a>`;
        });
    }

    /**
     * Turn all URLs in .caosdb-f-property-text-value DOM elements into actual links
     */
    var _linkify_all_text_values = function () {
        $('.caosdb-f-property-text-value').each(function (index) {
            if (!($(this).hasClass("caosdb-v-property-linkified")) && (/https?:\/\//.test(this.innerText))) {
                var linkified_text_value = linkify_string(this.innerText);
                // add class to highlight that this has been linkified already
                // (see https://gitlab.com/caosdb/caosdb-webui/-/issues/199).
                $(this).addClass("caosdb-v-property-linkified")
                $(this).hide();
                $(this).after(linkified_text_value);
            }
        });
    }

    /**
     * Convert any substring of a text-value beginning with 'http(s)://' into a
     * link.
     *
     * A listener detects edit-mode changes and previews
     */
    var linkify = function () {
        _linkify_all_text_values();

        // edit-mode-listener
        document.body.addEventListener(edit_mode.end_edit.type, _linkify_all_text_values, true);
        // preview listener
        document.body.addEventListener(preview.previewReadyEvent.type, _linkify_all_text_values, true);
    }

    /**
     * Customize datetime formatting.
     *
     * A listener detects edit-mode changes and previews
     */
    var custom_datetime = function () {
        _custom_datetime();

        // edit-mode-listener to delete replacement
        document.body.addEventListener(edit_mode.start_edit.type, _custom_datetime_clear, true);
        // edit-mode-listener to recreate
        document.body.addEventListener(edit_mode.end_edit.type, _custom_datetime, true);
        // preview listener
        document.body.addEventListener(preview.previewReadyEvent.type, _custom_datetime, true);
    }

    /**
     * Prettify double values for display purposes.
     */
    const prettify_double_values = () => {
        $('.caosdb-f-property-double-value').each(function (index) {
            if (!$(this).hasClass("caosdb-v-property-double-prettified")) {
                let value = parseFloat(this.innerText);
                let prettified_value = "";

                if (Math.abs(value) > 1e6 || Math.abs(value) < 1e-6) {
                    // Use scientific notation for very large or very small values
                    prettified_value = value.toExponential(1);
                } else {
                    // Otherwise, display with up to 12 significant digits
                    prettified_value = value.toPrecision(12).replace(/\.?0+$/, '');
                }

                $(this).addClass("caosdb-v-property-double-prettified");
                $(this).hide();
                $(this).after(`<span class="caosdb-v-property-double-prettified-newvalue">${prettified_value}</span>`);
            }
        });
    };

    this.init = function () {
        this.custom_datetime = custom_datetime;
        if ("${BUILD_MODULE_EXT_COSMETICS_CUSTOMDATETIME}" == "ENABLED") {
            custom_datetime();
        }
        this.linkify = linkify;
        if ("${BUILD_MODULE_EXT_COSMETICS_LINKIFY}" == "ENABLED") {
            linkify();
        }
        this.prettify_double_values = prettify_double_values;
        if ("${BUILD_MODULE_EXT_COSMETICS_PRETTIFY_DOUBLES}" === "ENABLED") {
            prettify_double_values();
        }
    }
}


$(document).ready(function () {
    caosdb_modules.register(cosmetics);
});