var currentScript = document.currentScript;
// const TRANSLATION_PLUGIN_API_KEY = currentScript.getAttribute('secretKey');
const posX = currentScript.getAttribute('data-pos-x') || 100;
const posY = currentScript.getAttribute('data-pos-y')|| 5;
let defaultTranslatedLanguage = currentScript.getAttribute('default-translated-language');
const languageListAttribute = currentScript.getAttribute('translation-language-list');
const TRANSLATION_PLUGIN_API_BASE_URL = new URL(currentScript.getAttribute('src')).origin;
let mixedCode = currentScript.getAttribute("mixed-code") || false;

const CHUNK_SIZE = 25;


// Define translationCache object to store original text
var translationCache = {};

// Flag to track whether content has been translated initially
var isContentTranslated = false;

// Selected target language for translation
var selectedTargetLanguageCode = "";

// Retrieve translationCache from session storage if available
if (sessionStorage.getItem('translationCache')) {
    translationCache = JSON.parse(sessionStorage.getItem('translationCache'));
}

var cssLink = document.createElement('link');
cssLink.rel = 'stylesheet';
cssLink.href = `${TRANSLATION_PLUGIN_API_BASE_URL}/website_translation_utility.css`;

// Append link to the head
document.head.appendChild(cssLink);

// Fetch supported translation languages
function fetchTranslationSupportedLanguages() {
    const targetLangSelectElement = document.getElementById("translate-plugin-target-language-list");
   const supportedTargetLangArr = [
        // { "code": "", "label": "Select" },
        { "code": "en", "label": "English" },
        { "code": "as", "label": "Assamese (অসমীয়া)"},
        { "code": "bn", "label": "Bengali (বাংলা)"},
        { "code": "brx", "label": "Bodo (बड़ो)"},
        { "code": "doi", "label": "Dogri (डोगरी)"},
        { "code": "gom", "label": "Goan Konkani (गोवा कोंकणी)"},
        { "code": "gu", "label": "Gujarati (ગુજરાતી)"},
        { "code": "hi", "label": "Hindi (हिन्दी)"},
        { "code": "kn", "label": "Kannada (ಕನ್ನಡ)"},
        { "code": "ks", "label": "Kashmiri (कश्मीरी)"},
        { "code": "mai", "label": "Maithili (मैथिली)"},
        { "code": "ml", "label": "Malayalam (മലയാളം)"},
        { "code": "mni", "label": "Manipuri (মণিপুরী)"},
        { "code": "mr", "label": "Marathi (मराठी)"},
        { "code": "ne", "label": "Nepali (नेपाली)"},
        { "code": "or", "label": "Odia (ଓଡ଼ିଆ)"},
        { "code": "pa", "label": "Punjabi (ਪੰਜਾਬੀ)"},
        { "code": "sa", "label": "Sanskrit (संस्कृत)"},
        { "code": "sat", "label": "Santali (संताली)"},
        { "code": "sd", "label": "Sindhi (سنڌي)"},
        { "code": "ta", "label": "Tamil (தமிழ்)"},
        { "code": "te", "label": "Telugu (తెలుగు)"},
        { "code": "ur", "label": "Urdu (اردو)"}
    ]
    if (languageListAttribute) { // If the languageList attribute is present
        // remove extra spaces and split the string into an array
        // so if the attribute is "en, hi, ta", it will be converted to ["en", "hi", "ta"]
        const languageList = languageListAttribute.split(",").map(lang => lang.trim());
        // Filter the supported languages based on the languageList
        const filteredLanguages = supportedTargetLangArr.filter(lang => 
            languageList.includes(lang.code)
        );
        // Loop through the filtered languages and create option elements for the dropdown
        filteredLanguages.forEach((element, index) => {
            let option_element = document.createElement("option");
            option_element.setAttribute("class", "dont-translate");
            option_element.value = element.code;
            option_element.textContent = element.label;
            // Set the first language as the default selected option
            if (index === 0) {
                option_element.setAttribute("selected", "selected");
            }
            targetLangSelectElement.appendChild(option_element);
        });
    } else { // If the languageList attribute is not present, create options for all supported languages
        supportedTargetLangArr.forEach(element => {
            let option_element = document.createElement("option");
            option_element.setAttribute("class", "dont-translate");
            option_element.value = element.code;
            option_element.textContent = element.label;
            targetLangSelectElement.appendChild(option_element);
        });
    }
}

// Function to split an array into chunks of a specific size
function chunkArray(array, size) {
    const chunkedArray = [];
    for (let i = 0; i < array.length; i += size) {
        chunkedArray.push(array.slice(i, i + size));
    }
    return chunkedArray;
}

// Function to get all input and textArea element with placeholders
function getInputElementsWithPlaceholders() {
    return Array.from(document.querySelectorAll("input[placeholder], textarea[placeholder]"));
  }

  async function translateTitleAttributes(element, target_lang) {
    const elementsWithTitle = element.querySelectorAll('[title]');
    const titleTexts = Array.from(elementsWithTitle).map(el => el.getAttribute('title'));

    if (titleTexts.length > 0) {
        const translatedTitles = await translateTextChunks(titleTexts, target_lang);
        elementsWithTitle.forEach((el, index) => {
            const translatedTitle = translatedTitles[index].target || titleTexts[index];
            el.setAttribute('title', translatedTitle);
        });
    }
}
  
  // Function to translate all input elements with placeholders
  async function translatePlaceholders(target_lang) {
      const inputs = getInputElementsWithPlaceholders();
      const placeholders = inputs.map(input => input.placeholder);
    
      if (placeholders.length > 0) {
        const translatedPlaceholders = await translateTextChunks(placeholders, target_lang);
        
        inputs.forEach((input, index) => {
          const translatedPlaceholder = translatedPlaceholders[index].target || placeholders[index];
          input.placeholder = translatedPlaceholder;
        });
      }
    }

// Function to translate text chunks using custom API
async function translateTextChunks(chunks, target_lang) {
    if (target_lang === "en") {
        return chunks.map(chunk => ({ source: chunk, target: chunk }));
    }
    const payload = {
        sourceLanguage: "en",
        targetLanguage: target_lang,
        textData: chunks
    }

    if (mixedCode === "true") {
        payload.mixed_code = true;
    }

    try {
        const response = await fetch(`${TRANSLATION_PLUGIN_API_BASE_URL}/v2/translate-text`, {
            method: 'POST',
            headers: {
                // 'auth-token': TRANSLATION_PLUGIN_API_KEY,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload),
        });
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error translating text:', error);
        return [];
    }
}

// Function to recursively traverse DOM tree and get text nodes while skipping elements with "dont-translate" class
function getTextNodesToTranslate(node, textNodes = []) {
    const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, null, false);
    while (walker.nextNode()) {
        const currentNode = walker.currentNode;
        const isNumeric = /^[\d.]+$/.test(walker.currentNode.data);
        const checkl = walker.currentNode.data.split("\n").join("").trim().length;
        if (!isIgnoredNode(currentNode) && checkl && !isNumeric) {
            textNodes.push(currentNode);
        }
    }
    return textNodes;
}

function isIgnoredNode(node) {
    const emailRegex = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b/;
    const govtEmailRegex =
    /^([a-zA-Z0-9]+(\[dot\])?)+(\[at\])([a-zA-Z0-9]+(\[dot\])?)+$/;
    return (
        node.parentNode &&
        (node.parentNode.tagName === "STYLE" ||
            node.parentNode.tagName === "SCRIPT" ||
            node.parentNode.tagName === "NOSCRIPT" ||
            node.parentNode.classList.contains('dont-translate') ||
            node.parentNode.classList.contains('bhashini-skip-translation') ||
            emailRegex.test(node.textContent) ||
            govtEmailRegex.test(node.textContent)
        ) 
    );
}


// Function to translate the text of an element
async function translateElementText(element, target_lang) {
    const promises = [];

    const textNodes = getTextNodesToTranslate(element);
    if (textNodes.length > 0) {
        // const textContentArray = textNodes.map(node => node.textContent.trim());
        // // if (target_lang !== "en") {
        //     const translatedTexts = await translateTextChunks(textContentArray, target_lang);
        //     textNodes.forEach((node, index) => {
        //         const translatedText = translatedTexts[index]?.target || textContentArray[index];
        //         node.nodeValue = translatedText;
        //     });
        // // }
        const textContentArray = textNodes.map((node, index) => {
            const id = `translation-${Date.now()}-${index}`;
            // Store original text in session storage
            translationCache[id] = node.textContent.trim();
            if (node.parentNode) {
                node.parentNode.setAttribute('data-translation-id', id);
            }
            return { text: node.textContent.trim(), id, node };
        });
        const textChunks = chunkArray(textContentArray, CHUNK_SIZE);

        // Create an array to hold promises for each chunk translation
        const textNodePromises = textChunks.map(async chunk => {
            const texts = chunk.map(({ text }) => text.trim());
            // if (target_lang === "en") {
            //         return;
            // }
            const translatedTexts = await translateTextChunks(texts, target_lang);
            chunk.forEach(({ id, node }, index) => {
                const translatedText = translatedTexts[index].target || texts[index];
                if (node.nodeValue.trim().length > 0) {
                    node.nodeValue = translatedText;
                }
            });
        });
        promises.push(textNodePromises);
        promises.push(translatePlaceholders(target_lang));
        promises.push(translateTitleAttributes(element, target_lang));
        await Promise.all(promises);
        // Wait for all translations to complete
        // await Promise.all(promises);
        // await translatePlaceholders(target_lang);
    }
}

document.addEventListener("DOMContentLoaded", function () {
    // Create translation popup elements
    const wrapperDiv = document.createElement('div');
    wrapperDiv.setAttribute("class", "dont-translate bhashini-skip-translation");
    wrapperDiv.setAttribute("id", "bhashini-translation");
    wrapperDiv.setAttribute("title", "Translate this page!");
    wrapperDiv.innerHTML = `<select class="translate-plugin-dropdown" id="translate-plugin-target-language-list"></select><img src=${TRANSLATION_PLUGIN_API_BASE_URL}/bhashini_logo.png alt="toggle translation popup">`;

    // Append the wrapperDiv to the body or any other container
    document.body.appendChild(wrapperDiv);

    // Now that the element is in the DOM, its dimensions can be calculated
    const width = wrapperDiv.offsetWidth;

    // Set the position using the calculated width
    

    // Set the position using the calculated width
    const calculatedPosX = posX - (218 * 100 / window.innerWidth);
    const adjustedPosX = calculatedPosX < 0 ? posX : calculatedPosX;
    wrapperDiv.style.left = `${adjustedPosX}%`;
    const calculatedPosY = posY - (58 * 100 / window.innerHeight);
    const adjustedPosY = calculatedPosY < 0 ? posY : calculatedPosY;
    wrapperDiv.style.bottom = `${adjustedPosY}%`;
    // Add event listener for dropdown change
    const targetLanguageList = document.getElementById("translate-plugin-target-language-list");
    if (targetLanguageList) {
        targetLanguageList.addEventListener('change', onDropdownChange);
    }
    // Fetch supported translation languages
    fetchTranslationSupportedLanguages();

    // Create a new MutationObserver
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.type === 'childList' && mutation.target.innerHTML) {
// If a new element is added, replaced, or changed, translate its text nodes
// const targetLang = document.getElementById("translate-plugin-target-language-list").value;
                if (selectedTargetLanguageCode) {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            translateElementText(node, selectedTargetLanguageCode);
                            translatePlaceholders(selectedTargetLanguageCode);
                        }
                    });
                }
            }
        });
    });

    // Start observing the document body for changes
    observer.observe(document.body, { childList: true, subtree: true });

    // Add event listener for window resize to adjust widget position
    window.addEventListener("resize", adjustWidgetPosition);

    // Adjust the widget position on initial load
    adjustWidgetPosition();

    // check if isSelectedLangEnglish is present in sessionStorage 
    const isSelectedLang = sessionStorage.getItem("selectedLang");
    if (isSelectedLang) {
        sessionStorage.removeItem("selectedLang");
        defaultTranslatedLanguage = null;
    }
    
    /**
     * Check if the defaultTranslatedLanguage is present and not equal to "en", then set the language to the defaultTranslatedLanguage
     * Otherwise, set the language to the preferred language stored in localStorage
     */
    const languageToUse = defaultTranslatedLanguage && defaultTranslatedLanguage !== "en" 
        ? defaultTranslatedLanguage 
        : localStorage.getItem('preferredLanguage');
    if (languageToUse) {
        selectedTargetLanguageCode = languageToUse;
        document.getElementById("translate-plugin-target-language-list").value = languageToUse;
        isContentTranslated = true;
        translateAllTextNodes(languageToUse);
    }
    
    
    
});

// Function to handle dropdown change
function onDropdownChange(event) {
    const selectedValue = event.target.value;
    // If English is selected, restore translations from session storage
    // if (selectedValue && selectedValue === "en" && isContentTranslated) {
    //     // selectedTargetLanguageCode = ""
    //     // restoreTranslations();
    //     localStorage.removeItem('preferredLanguage');
    //     window.location.reload();
    // } else if(selectedValue && selectedValue !== "en") {
    //     selectedTargetLanguageCode = selectedValue;
    //     isContentTranslated = true;
    //     // Store preferred language in localStorage
    //     localStorage.setItem('preferredLanguage', selectedValue);
    //     sessionStorage.setItem("isSelectedLang",selectedValue);

    //     // Perform translation for the selected language
    //     translateAllTextNodes(selectedTargetLanguageCode);
    //     // showToast(`This page is translated using Bhashini's Machine Learning models.`);
    // }
    isContentTranslated = true;
    sessionStorage.setItem("selectedLang", selectedValue);
        // Store preferred language in localStorage
    localStorage.setItem('preferredLanguage', selectedValue);
    // Perform translation for the selected language
    // translateAllTextNodes(selectedValue);
    window.location.reload();
}

// Function to show a toast messages
function showToast(message) {
    const toast = document.createElement('div');
    toast.className = 'bhashini-toast';
    toast.textContent = message;
    document.body.appendChild(toast);
    setTimeout(() => {
        toast.classList.add('visible');
        toast.classList.add('bhashini-skip-translation');
    }, 100);
    setTimeout(() => {
        toast.classList.remove('visible');
        setTimeout(() => {
            document.body.removeChild(toast);
        }, 300);
    }, 3000);
}

// Function to restore translations from session storage
function restoreTranslations() {
    const textNodes = getTextNodesToTranslate(document.body);
    textNodes.forEach(node => {
        const id = node.parentNode.getAttribute('data-translation-id');
        if (id && translationCache[id]) {
            node.nodeValue = translationCache[id];
        }
    });
    fetchTranslationSupportedLanguages();
}

// Function to translate all text nodes in the document
async function translateAllTextNodes(target_lang) {
    const promises = [];
    const textNodes = getTextNodesToTranslate(document.body);
    if (textNodes.length > 0) {
        const textContentArray = textNodes.map((node, index) => {
            const id = `translation-${Date.now()}-${index}`;
            // Store original text in session storage
            translationCache[id] = node.textContent.trim();
            if (node.parentNode) {
                node.parentNode.setAttribute('data-translation-id', id);
            }
            return { text: node.textContent.trim(), id, node };
        });
        const textChunks = chunkArray(textContentArray, CHUNK_SIZE);

        // Create an array to hold promises for each chunk translation
        const textNodePromises = textChunks.map(async chunk => {
            const texts = chunk.map(({ text }) => text.trim());
            // if (target_lang === "en") {
            //         return;
            // }
            const translatedTexts = await translateTextChunks(texts, target_lang);
            chunk.forEach(({ id, node }, index) => {
                const translatedText = translatedTexts[index].target || texts[index];
                if (node.nodeValue.trim().length > 0) {
                    node.nodeValue = translatedText;
                }
            });
        });

        // Wait for all translations to complete
        promises.push(textNodePromises);
        promises.push(translatePlaceholders(target_lang));  
        promises.push(translateTitleAttributes(document.body, target_lang));
        await Promise.all(promises);

        const targetLangSelectElement = document.getElementById("translate-plugin-target-language-list");
        // Check if the targetLangSelectElement exists
        if (targetLangSelectElement) {
            // Loop through each option element
            Array.from(targetLangSelectElement.options).forEach(option => {
                // Check if the value is not "en", not equal to target_lang, and not an empty string
                if (option.value === target_lang) {
                    // Keep the default selected option if it's the target language
                    option.selected = true;
                }
            });
        } else {
            console.error('Target language select element not found.');
        }
        showToast(`This page is translated using Bhashini's Machine Learning models.`);
    }
}

// Store translationCache in session storage
sessionStorage.setItem('translationCache', JSON.stringify(translationCache));

// Function to adjust widget position based on device width
const adjustWidgetPosition = () => {
    const wrapperDiv = document.getElementById("bhashini-translation");
    if (window.innerWidth <= 768) {
      // Position for mobile devices
      wrapperDiv.style.left = `calc(100vw - ${wrapperDiv.offsetWidth + 10}px)`;
      wrapperDiv.style.bottom = `10px`;
    } else if (window.innerWidth <= 1024) {
      // Position for tablet devices
      wrapperDiv.style.left = `calc(100vw - ${wrapperDiv.offsetWidth + 20}px)`;
      wrapperDiv.style.bottom = `20px`;
    } 
}

// CSS for toast message
const toastStyles = `
    .bhashini-toast {
        position: fixed;
        left: 50%;
        bottom: 20px;
        transform: translateX(-50%);
        background-color: rgba(0, 0, 0, 0.7);
        color: white;
        padding: 10px 20px;
        border-radius: 5px;
        opacity: 0;
        transition: opacity 0.3s ease, bottom 0.3s ease;
        z-index: 10000;
    }
    .bhashini-toast.visible {
        opacity: 1;
        bottom: 40px;
    }
`;
const styleSheet = document.createElement('style');
styleSheet.innerText = toastStyles;
document.head.appendChild(styleSheet);
