import i18next from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import HttpApi from "i18next-http-backend";
import '@fortawesome/fontawesome-free/js/fontawesome'
import '@fortawesome/fontawesome-free/js/solid'
import '@fortawesome/fontawesome-free/js/regular'
import '@fortawesome/fontawesome-free/js/brands'
import './main.scss';

/////////////////
// TRANSLATION //
/////////////////

async function initI18next() {
    await i18next
        .use(HttpApi)
        .use(LanguageDetector)
        .init({
            supportedLngs: ["en", "de"],
            nonExplicitSupportedLngs: true,
            fallbackLng: "en",
            debug: true,
            backend: {
                loadPath: "/i18n/{{lng}}.json",
            },
        });
}

function translatePageElements() {
    // Translate content inside a tag
    const translatableElements = document.querySelectorAll(
        "[data-i18n-key]",
    );
    translatableElements.forEach((el) => {
        const key = el.getAttribute("data-i18n-key");
        el.innerHTML = i18next.t(key);
    });
    // Translate alt texts
    const translatableAltTexts = document.querySelectorAll(
        "[alt-i18n-key]",
    );
    translatableAltTexts.forEach((el) => {
        const translation_key = el.getAttribute("alt-i18n-key");
        el.setAttribute("alt", i18next.t(translation_key));
    });

}

function bindLocaleSwitcher(initialValue) {
    const switcher = document.querySelector(
        "[data-i18n-switcher]",
    );
    switcher.value = initialValue;
    switcher.onchange = (e) => {
        i18next
            .changeLanguage(e.target.value)
            .then(translatePageElements)
            .then(update);
    };
}

(async function () {
    await initI18next();
    translatePageElements();
    bindLocaleSwitcher(i18next.resolvedLanguage);
    update();
})();

//////////
// TABS //
//////////



function initTabs(tabs, tabContent, activationClass) {
    tabs.forEach((tab) => {
        tab.addEventListener('click', (e) => {
            let selectedTabID = tab.getAttribute('data-tab-id');
            updateActiveTab(tabs, tab);
            updateActiveContent(tabContent, selectedTabID);
        })
    })
}

function updateActiveTab(tabs, selectedTabID) {
    tabs.forEach((tab) => {
        if (tab && tab.classList.contains(ACTIVATION_CLASS)) {
            tab.classList.remove(ACTIVATION_CLASS);
        }
    });
    selectedTabID.classList.add(ACTIVATION_CLASS);
}

function updateActiveContent(tabsContent, selectedTabID) {
    tabsContent.forEach((item) => {
        if (item && item.classList.contains(ACTIVATION_CLASS)) {
            item.classList.remove(ACTIVATION_CLASS);
        }
        let data = item.getAttribute('data-content-id');
        if (data === selectedTabID) {
            item.classList.add(ACTIVATION_CLASS);
        }
    });
}

const primaryTabs = [...document.querySelectorAll('#primary-tabs li')];
const primaryTabsContent = [...document.querySelectorAll('#tab-content div')];
const ACTIVATION_CLASS = 'is-active';

initTabs(primaryTabs, primaryTabsContent, ACTIVATION_CLASS);


////////////////
// CALCULATOR //
////////////////

const MINIMUM_BASE_AREA = 0.5;
const MINIMUM_AREA_THREE_RATS = 1.5;
const AREA_PER_ADDITIONAL_RAT = 0.25;
const MAXIMUM_FALL_HEIGHT = 0.5;
const MINIMUM_LENGTH_LONG_SIDE = 0.8;
const MINIMUM_LENGTH_SHORT_SIDE = 0.5;
const MINIMUM_FLOOR_HEIGHT = 0.25;

const FAILED_BASE_AREA = "base_area";
const FAILED_OVERALL_AREA = "overall_area";
const FAILED_FALL_HEIGHT = "fall_height";
const FAILED_NUM_RATS = "num_rats";
const FAILED_MINIMUM_LENGTH_LONG_SIDE = "length_long_side";
const FAILED_MINIMUM_LENGTH_SHORT_SIDE = "length_short_side";
const FAILED_FLOOR_HEIGHT = "floor_height"


class Validator {
    constructor() {
        this.FAIL_CRITERIA = {
            [FAILED_BASE_AREA]: i18next.t('failed-base-area', {"MINIMUM_BASE_AREA": MINIMUM_BASE_AREA}),
            [FAILED_OVERALL_AREA]: i18next.t("failed-overall-area"),
            [FAILED_FALL_HEIGHT]: i18next.t("failed-fall-height", {"maximum_fall_height": (MAXIMUM_FALL_HEIGHT * 100).toFixed(0)}),
            [FAILED_FLOOR_HEIGHT]: i18next.t("failed-floor-height", {"minimum_floor_height": (MINIMUM_FLOOR_HEIGHT * 100).toFixed(0)}),
            [FAILED_NUM_RATS]: i18next.t("failed-num-rats"),
            [FAILED_MINIMUM_LENGTH_LONG_SIDE]: i18next.t("failed-minimum-length-long-side", {"minimum_length_long_side": (MINIMUM_LENGTH_LONG_SIDE * 100).toFixed(0)}),
            [FAILED_MINIMUM_LENGTH_SHORT_SIDE]: i18next.t("failed-minimum-length-short-side", {"minimum_length_short_side": (MINIMUM_LENGTH_SHORT_SIDE * 100).toFixed(0)}),
        };
    }

    overallAreaNeeded(numOfRats) {
        if (numOfRats < 3 || numOfRats > 15) {
            throw new Error("This formula works only from 3 to 15 rats");
        }
        return MINIMUM_AREA_THREE_RATS + (numOfRats - 3) * AREA_PER_ADDITIONAL_RAT;
    }

    cageCheck(dimensions, numRats, numFullFloors) {
        let failedCriteria = {};

        if (numRats < 2 || numRats > 15) {
            failedCriteria[FAILED_NUM_RATS] = this.FAIL_CRITERIA[FAILED_NUM_RATS];
        }

        const baseArea = dimensions.depth * dimensions.width;
        if (baseArea < MINIMUM_BASE_AREA) {
            failedCriteria[FAILED_BASE_AREA] = this.FAIL_CRITERIA[FAILED_BASE_AREA];
        }

        const areaNeeded = this.overallAreaNeeded(numRats);
        if (baseArea * numFullFloors < areaNeeded) {
            failedCriteria[FAILED_OVERALL_AREA] = this.FAIL_CRITERIA[FAILED_OVERALL_AREA];
        }

        if (dimensions.height / numFullFloors > MAXIMUM_FALL_HEIGHT) {
            failedCriteria[FAILED_FALL_HEIGHT] = this.FAIL_CRITERIA[FAILED_FALL_HEIGHT];
        }

        if (dimensions.width < MINIMUM_LENGTH_LONG_SIDE && dimensions.depth < MINIMUM_LENGTH_LONG_SIDE) {
            failedCriteria[FAILED_MINIMUM_LENGTH_LONG_SIDE] = this.FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_LONG_SIDE];
        }

        if (dimensions.width < MINIMUM_LENGTH_SHORT_SIDE || dimensions.depth < MINIMUM_LENGTH_SHORT_SIDE) {
            failedCriteria[FAILED_MINIMUM_LENGTH_SHORT_SIDE] = this.FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_SHORT_SIDE];
        }

        if (dimensions.height / numFullFloors < MINIMUM_FLOOR_HEIGHT) {
            failedCriteria[FAILED_FLOOR_HEIGHT] = this.FAIL_CRITERIA[FAILED_FLOOR_HEIGHT];
        }

        return failedCriteria;
    }


}

class Dimensions {
    constructor(width, depth, height) {
        this.width = width;
        this.depth = depth;
        this.height = height;
    }

    toString() {
        return `${this.width}x${this.depth}x${this.height}`;
    }

    static fromDict(data) {
        const {width, depth, height} = data;
        return new Dimensions(width, depth, height);
    }
}


//////////////////////////
// DOCUMENT INTERACTION //
//////////////////////////

const inputWidth = document.getElementById("width");
inputWidth.onchange = updateViaManualMeasurements;
const inputDepth = document.getElementById("depth");
inputDepth.onchange = updateViaManualMeasurements;
const inputHeight = document.getElementById("height");
inputHeight.onchange = updateViaManualMeasurements;



let labelNumRats = document.getElementById("labelNumRats");

let ratSlider = document.getElementById("numRats");

ratSlider.oninput = function () {
    update();
}

// Full floor functions
let fullFloorNum = document.getElementById("numFullFloors");
fullFloorNum.oninput = function () {
    update();
}

function getResultFromChecks(checks) {
    if (Object.keys(checks).length > 0) {
        const ul = document.createElement('ul');
        for (const key in checks) {
            const li = document.createElement('li');
            li.textContent = `❌ ` + checks[key];
            ul.appendChild(li);
        }
        return ul;
    } else {
        const p = document.createElement('p');
        p.innerHTML = "✅ " + i18next.t("cage-complies-with-all-criteria")
        return p;
    }

}

function updateViaManualMeasurements() {
    update();
}

function update() {
    labelNumRats.innerHTML = i18next.t("cage-for-x-rats", {"num_rats": ratSlider.value});

    const width = inputWidth.value
    const depth = inputDepth.value
    const height = inputHeight.value
    const dimensions = new Dimensions(width / 100, depth / 100, height / 100);
    const validator = new Validator();
    const failed_checks = validator.cageCheck(dimensions, ratSlider.value, fullFloorNum.value);
    let resultsDiv = document.getElementById("resultsDiv");

    const result = getResultFromChecks(failed_checks);

    resultsDiv.innerHTML = "";
    resultsDiv.appendChild(result);
}
