import { state } from './state.js';
import { toggleFields, makeButton } from './home.js';

var failureCount = state.saveFailureCount;

/**
 * Retrieves a note from the server based on the provided ID.
 *
 * @param {string} id - The ID of the note to retrieve.
 * @param {boolean} [runOpen=true] - Whether to open the note sidebar after retrieving the note.
 * @return {Promise<void>} A promise that resolves when the note is successfully retrieved and the UI is updated.
 */
export function retrieveNote(id, runOpen = true) {
    fetch('/get-note', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'id': id
        })
    })
        .then(response => response.json())
        .then(result => {
            var dt = new Date(result.date.date);

            document.querySelector('#notes').value = result.text;
            document.querySelector('#passage').value = result.passage;
            document.querySelector('#series').value = result.series.id;
            document.querySelector('#speaker').value = result.speaker.id;
            document.querySelector('#noteTitle').value = result.title;
            document.querySelector('#noteDate').value = '';
            document.querySelector('#noteDate').value =
                (dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '/' +
                (dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()) + '/' +
                dt.getFullYear();
            document.querySelector('#noteId').value = result.id;

            if (result.recording) {
                document.querySelector('#recording').value = result.recording;
            }

            if (result.refs) {
                state.references = result.refs;
            }

            const list = document.querySelector('#ref-list');
            list.innerHTML = '';
            var newList = null;
            for (var x in state.references) {
                var newList = document.createElement('li');
                newList.className = 'tab';
                var button = makeButton(x);
                newList.appendChild(button);
                list.appendChild(newList);
            }

            if (runOpen) {
                note.openNote(false);
            }
        });
}

/**
 * Toggles the visibility of the note list and reference elements.
 *
 * @param {boolean} [openSidebar=true] - Whether to open the sidebar after toggling the visibility.
 * @return {void}
 */
export function openNote(openSidebar = true) {
    const noteList = document.querySelector('#note-list');
    const refs = document.querySelector('#ref-text');

    if (noteList.style.display == 'block') {
        noteList.style.display = 'none';
        refs.style.display = 'block';
    } else {
        noteList.style.display = 'block';
        refs.style.display = 'none';
    }

    if (openSidebar && !document.querySelector('.container').classList.contains('sidebar-collapsed')) {
        document.querySelector('.container').classList.add('sidebar-collapsed');
    }
}

/**
 * Starts the save process by updating the save-check element's classList, removing error, fa-times-circle, and fa-save classes,
 * adding the 'saving' and 'fa-save' classes, and setting the opacity to 1.
 *
 * @return {void} This function does not return anything.
 */
export function startSave() {
    document.querySelector('#save-check').classList.remove('error', 'fa-times-circle', 'fa-save');
    document.querySelector('#save-check').classList.add('saving', 'fa-save');
    document.querySelector('#save-check').style.opacity = 1;
}

/**
 * Displays a checkmark animation on the screen.
 *
 * @param {none} - This function does not take any parameters.
 * @return {none} - This function does not return any value.
 */
export function showSave() {
    if (state.saved) { return; }

    var checkmark = document.getElementById("save-check");
    checkmark.classList.add('fa-save');

    // Schedule the animation to run every 1 second (which is equivalent to a 1-second delay between each iteration)
    var si = setInterval(function () {
        // Increment the opacity of the checkmark by 0.01 each time
        let op = parseFloat(checkmark.style.opacity);
        checkmark.style.opacity = op - 0.1;

        // If the opacity is greater than or equal to 1, reset it back to 0 and stop the animation
        if (checkmark.style.opacity == 0.1) {
            checkmark.style.opacity = 0;
            clearInterval(si);
            state.saved = false;
        }
    }, 100);
}

/**
 * function to discard the note by clearing all input fields and closing the menu.
 */
export function deleteNote(noteId, link) {
    document.querySelector('#noteTitle').value = '';
    document.querySelector('#speaker').value = 0;
    document.querySelector('#series').value = 0;
    document.querySelector('#template').value = 0;
    document.querySelector('#passage').value = '';
    document.querySelector('#notes').value = '';
    document.querySelector('#recording').value = '';
    document.querySelector('#noteDate').value = '';
    document.querySelector('#noteId').value = '';

    var row = link.parentElement.parentElement;

    fetch('/delete-note', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'id': noteId
        })
    })
        .then(response => response.json())
        .then(data => {
            if (data.msg != 'deleted') {
                return;
            }

            alert('Note deleted.');
            row.remove();
        });
}

/**
 * Validates a note by checking if all required fields are filled.
 *
 * @return {boolean} Returns true if all required fields are filled, false otherwise.
 */
export function validateNote() {
    const note = document.querySelector('#notes');
    const date = document.querySelector('#noteDate');
    const speaker = document.querySelector('#speaker');
    const series = document.querySelector('#series');
    const title = document.querySelector('#noteTitle');
    const psg = document.querySelector('#passage');

    let ret = true;

    if (!title.value.length) { title.classList.add('input-error'); ret = false; }
    if (!date.value) { date.classList.add('input-error'); ret = false; }
    if (!parseInt(speaker.value)) { speaker.classList.add('input-error'); ret = false; }
    if (!parseInt(series.value)) { series.classList.add('input-error'); ret = false; }
    if (!psg.value) { psg.classList.add('input-error'); ret = false; }
    if (!note.value.length) { note.classList.add('input-error'); ret = false; }

    if (!ret) {
        toggleFields(null, true);
    }

    return ret;
}

/**
 * Resets the state of the note editor by clearing the text and form fields,
 * resetting the references, and removing any dirty classes. It also sets the
 * date to the current date, clears the speaker, series, template, passage,
 * recording, and note ID fields. Finally, it clears the reference list and
 * reference display.
 *
 * @return {void} This function does not return anything.
 */
export function newNote() {
    var notes = document.querySelector('#notes');
    notes.text = '';
    notes.value = '';
    state.references = {};
    state.saved = true;
    state.textDirty = false;
    document.querySelector('.note-header-column h2').classList.remove('dirty');

    var dt = new Date();
    document.querySelector('#noteDate').value = dt.getFullYear() + '-' +
        (dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' +
        (dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate());
    document.querySelector('#noteTitle').value = '';
    document.querySelector('#speaker').value = 0;
    document.querySelector('#series').value = 0;
    document.querySelector('#template').value = 0;
    document.querySelector('#passage').value = '';
    document.querySelector('#recording').value = '';
    document.querySelector('#noteId').value = '';

    document.querySelector('#ref-list').innerHTML = '';
    document.querySelector('#ref-text').innerHTML = '';
    document.querySelector('.container').classList.add('sidebar-collapsed');
}

/**
 * Save a note by sending it to the server for storage.
 *
 * @param {Event} event - The event object triggering the save action.
 * @return {void} No explicit return value.
 */
export function saveNote(event) {
    //console.debug('called saveNote '+new Date());
    if (event) {
        event.preventDefault();
    }

    if (!state.textDirty) {
        clearTimeout(state.to);
        state.to = setTimeout(saveNote, state.saveInterval);
        return;
    }

    document.querySelector('#noteTitle').classList.remove('input-error');
    document.querySelector('#noteDate').classList.remove('input-error');
    document.querySelector('#speaker').classList.remove('input-error');
    document.querySelector('#series').classList.remove('input-error');
    document.querySelector('#passage').classList.remove('input-error');
    document.querySelector('#notes').classList.remove('input-error');

    if (!validateNote()) {
        clearTimeout(state.to);
        state.to = setTimeout(saveNote, state.saveInterval);
        return;
    }

    let saveCheck = document.querySelector('#save-check');
    var noteText = document.querySelector('#notes').value;

    startSave();

    var note = {
        id: document.querySelector("#noteId").value,
        date: document.querySelector('#noteDate').value,
        title: document.querySelector('#noteTitle').value,
        speaker: document.querySelector('#speaker').value,
        series: document.querySelector('#series').value,
        passage: document.querySelector('#passage').value,
        note: document.querySelector('#notes').value,
        recording: document.querySelector('#recording').value,
        refs: state.references
    };
    $.ajax({
        url: '/save-note',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(note),
        dataType: 'json',
        timeout: state.saveTimeout
    })
        .done(function (data) {
            if (data.msg == 'saved' && !state.saved) {
                saveCheck.classList.remove('saving', 'error', 'fa-times-circle', 'fa-save');
                showSave();
                if (noteText == document.querySelector('#notes').value) {
                    state.saved = true;
                    state.textDirty = false;
                    document.querySelector('.note-header h2').classList.remove('dirty');
                    document.querySelector('.mobile-note-header h2').classList.remove('dirty');
                }

                if (data.new) {
                    document.querySelector('#noteId').value = data.id;
                }
            }
        })
        .fail(function (xhr, status, error) {
            state.failureCount--;
            saveCheck.classList.remove('saving', 'fa-save');
            saveCheck.classList.add('fa-times-circle', 'error');
            console.error(error);
        })
        .always(function (xhr, status) {
            if (status == 'timeout') {
                saveCheck.classList.remove('saving', 'fa-save');
                saveCheck.classList.add('error', 'fa-times-circle');
            }
            clearTimeout(state.to);
            if (state.failureCount > 0) {
                state.to = setTimeout(saveNote, state.saveInterval);
            } else {
                state.failureCount = state.saveFailureCount;
            }
        });
}

/**
 * Function that finds reference links and fetches passage data when clicked.
 */
export function findRefLinks() {
    var links = document.querySelector('#ref-text').querySelectorAll('a');

    for (var i = 0; i < links.length; i++) {
        links[i].addEventListener('click', function (e) {
            e.preventDefault();
            if (!this.href.includes('get-passage')) {
                return;
            }
            var passage = this.href.split('/');
            passage = passage[passage.length - 1];

            fetch(this.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    'passage': passage
                })
            })
                .then(response => response.text())
                .then(result => {
                    let psg, book, cv;

                    passage = passage.replace(/\+/g, ' ');
                    psg = passage.split(' ');
                    if (psg.length > 2) {
                        book = psg[0] + ' ' + psg[1];
                        cv = psg[2];
                    } else {
                        book = psg[0];
                        cv = psg[1];
                    }
                    showPassage(
                        e,
                        "<button onclick='note.closePopup()'>Close</button>&nbsp;&nbsp;" +
                        "<button onclick=\"ref.queryRef(event, 'bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
                        result);
                });
        });
    }
}

/**
 * Finds all links in the note preview and adds event listeners to them.
 *
 * @return {void}
 */
export function findLinks() {
    var links = document.querySelector('#notePreview').querySelectorAll('a');

    for (var i = 0; i < links.length; i++) {
        links[i].addEventListener('click', function (e) {
            e.preventDefault();
            if (!this.href.includes('get-passage')) {
                return;
            }
            var passage = this.href.split('/');
            passage = passage[passage.length - 1];

            fetch(this.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    'passage': passage
                })
            })
                .then(response => response.text())
                .then(result => {
                    passage = passage.replace(/\+/g, ' ');
                    psg = passage.split(' ');
                    if (psg.length > 2) {
                        book = psg[0] + ' ' + psg[1];
                        cv = psg[2];
                    } else {
                        book = psg[0];
                        cv = psg[1];
                    }
                    showPassage(
                        e,
                        "<button onclick='note.closePopup()'>Close</button>&nbsp;&nbsp;" +
                        "<button onclick=\"ref.queryRef(event, 'bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
                        result);
                });
        });
    }
}

/**
 * Shows a passage in a popup element relative to the cursor position.
 *
 * @param {Event} event - The event that triggered the function.
 * @param {string} text - The text to be displayed in the popup.
 * @return {void} This function does not return a value.
 */
export function showPassage(event, text) {
    // Create a new div element for the popup
    const popup = document.querySelector('#passage-popup');
    popup.innerHTML = state.md.render(text);
    
    // Position the popup relative to the cursor
    let x = event.clientX + window.scrollX;
    let y = event.clientY + window.scrollY;

    // Set the position of the popup element
    popup.style.top = `${y}px`;
    popup.style.left = `${x}px`;
    popup.style.display = 'block';
    popup.style.position = 'absolute';
}

/**
 * Closes the passage popup by clearing its content and hiding it.
 *
 * @return {void} This function does not return anything.
 */
export function closePopup() {
    const popup = document.querySelector('#passage-popup');
    popup.innerHTML = '';
    popup.style.display = 'none';
}

/**
 * Opens the share note functionality.
 */
export function openShareNote() {
    let id = document.querySelector('#noteId').value;
    if (!id) {
        alert('No Open Note Found');
        return;
    }

    let bd = document.querySelector('#modal-backdrop');
    bd.style.display = 'block';
    let cont = document.querySelector('#modal-container');
    cont.style.display = bd.style.display;

    let emailCont = document.querySelector('#modal-container');
    emailCont.style.left = ((window.innerWidth / 2) - (emailCont.clientWidth / 2)) + 'px';
    emailCont.style.top = ((window.innerHeight / 2) - (emailCont.clientHeight / 2)) + 'px';
}

/**
 * Closes the share note modal by hiding the backdrop and container,
 * and clears the email input value.
 */
export function closeShareNote() {
    var bd = document.querySelector('#modal-backdrop');
    var cont = document.querySelector('#modal-container');
    bd.style.display = 'none';
    cont.style.display = 'none';
    document.querySelector('#shareEmail').value = '';
}

/**
 * Function to share a note by sending the note ID and email to the server.
 */
export function shareNote(event) {
    var id = document.querySelector('#noteId').value;
    var email = document.querySelector('#shareEmail').value;
    if (!id || !email) {
        alert('Invalid Input');
        return;
    }

    fetch('/share-note', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'id': id,
            'email': email
        })
    })
        .then(response => response.json())
        .then(result => {
            if (result) {
                alert(result.msg);
            }
        });

    closeShareNote();
}

