import * as note from './note.js';
import { state } from './state.js';
import * as ref from './reference.js';

// Get the link element
var tabs = [];
let controller;

// Function to change the CSS file based on checkbox state
/**
 * Method to toggle dark/light mode
 * 
 * @param {*} event 
 */
export function toggleDarkMode(event) {
    let mainCssLink = $('link[data-css="mode"');
    if(mainCssLink.length > 0) {
        mainCssLink[0].href = (event.target.checked ? mainCssLink.data('dark') : mainCssLink.data('light'));
    }
}

/**
 * Toggles the visibility of the fields container and updates the active state of the show/hide button.
 *
 * @param Event e
 * @param boolean forceShow
 * @return {void}
 */
export function toggleFields(e, forceShow = false) {
    const fieldsContainer = document.querySelector('.fields-container');
    let showHideBtn = document.getElementById('show-hide-btn');
    let mobileShowHideBtn = document.getElementById('mobile-show-hide-btn');

    if (forceShow || !fieldsContainer.classList.contains('show')) {
        fieldsContainer.classList.add('show');
        fieldsContainer.style.display = 'flex';
        showHideBtn.classList.add('active');
        mobileShowHideBtn.classList.add('active');
    } else {
        fieldsContainer.classList.remove('show');
        fieldsContainer.style.display = 'none';
        showHideBtn.classList.remove('active');
        mobileShowHideBtn.classList.remove('active');
    }
}

/**
 * Increases the font size of the element with the id 'ref' by 1 point.
 *
 * @return {void} This function does not return a value.
 */
export function increaseFont() {
    var currentSize = document.querySelector('#ref-text').style.fontSize;
    const newSize = parseInt(currentSize) + 1;
    document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
    document.querySelector('#notes').style.fontSize = newSize + 'pt';
    document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
}

/**
 * Decreases the font size of the element with the id 'ref' by 1 point.
 *
 * @return {void} This function does not return a value.
 */
export function decreaseFont() {
    var currentSize = document.querySelector('#ref-text').style.fontSize;
    const newSize = parseInt(currentSize) - 1;
    document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
    document.querySelector('#notes').style.fontSize = newSize + 'pt';
    document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
}

/**
 * Previews a note by rendering the markdown content of the note in a preview section.
 * Toggles between the note text and preview sections.
 *
 * @return {void} This function does not return anything.
 */
export function previewNote() {
    var noteText = document.querySelector('#notes');
    var notePreview = document.querySelector('#notePreview');
    var previewButton = document.querySelector('#previewBtn');

    const title = document.querySelector('#noteTitle');
    const speaker = document.querySelector('#speaker');
    const passage = document.querySelector('#passage');

    const markdownPreview = "# " + title.value + " - " +
        speaker.options[speaker.selectedIndex].text + " - " + passage.value + "\n\n" + noteText.value;

    notePreview.innerHTML = state.md.render(markdownPreview);

    if (previewButton.classList.contains('active')) {
        document.querySelector('.note-text').style.display = 'block';
        notePreview.style.display = 'none';
        previewButton.classList.remove('active');
    } else {
        document.querySelector('.note-text').style.display = 'none';
        notePreview.style.display = 'block';
        previewButton.classList.add('active');
    }

    note.findLinks();
}

/**
 * Sets event listeners for keyup events on the document and the '#notes' element.
 *
 * @return {void}
 */
export function setEventListeners() {
    document.addEventListener('keyup', function (event) {
        if (event.key == "F3") {
            openRef();
        }
    });

    document.querySelector('#notes').addEventListener('keyup', function (event) {
        let key = event.keyCode;

        if (key == 8 || key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) {
            state.saved = false
            state.textDirty = true;
            document.querySelector('.mobile-note-header h2').classList.add('dirty');
            document.querySelector('.note-header h2').classList.add('dirty');

            if(state.failureCount > 0 && !state.to) {
                state.to = setTimeout(note.saveNote, state.saveTimeout);
            }
        }
    });

    document.getElementById('dark-mode-checkbox').addEventListener('click', toggleDarkMode);
    document.getElementById('mobile-dark-mode-checkbox').addEventListener('click', toggleDarkMode);

    document.getElementById('show-hide-btn').addEventListener('click', toggleFields);
    document.getElementById('mobile-show-hide-btn').addEventListener('click', toggleFields);

    document.getElementById('increaseFont').addEventListener('click', increaseFont);
    document.getElementById('decreaseFont').addEventListener('click', decreaseFont);

    const openRefBtn = document.getElementById('open-ref');
    openRefBtn.addEventListener('click', openRef);
    openRefBtn.closeSidebar = true;
    const mobileOpenRefBtn = document.getElementById('mobile-open-ref');
    mobileOpenRefBtn.addEventListener('click', openRef);
    mobileOpenRefBtn.closeSidebar = true;

    document.getElementById('previewBtn').addEventListener('click', previewNote);
    //document.getElementById('shareBtn').addEventListener('click', note.openShareNote);
    document.getElementById('searchBtn').addEventListener('click', ref.queryRef);
    document.getElementById('closeSearch').addEventListener('click', closeRef);
}

export function initHome() {
    setBooks();
    setEventListeners();

    // expand the sidebar by default if we are on a large screen
    if(document.body.clientWidth >= 1501) {
        document.querySelector('.container').classList.remove('sidebar-collapsed');
    }

    $('#note-table').DataTable({
        paging: false,
        ajax: {
            url: '/get-notes',
            type: 'POST'
        },
        columns: [
            { data: 'link' },
            { data: 'speaker.name' },
            { data: 'passage' },
            {
                data: 'date.date',
                render: DataTable.render.date("L")
            },
        ]
    });
    $('#note-table').css('width', '100%');
    $('#shareBtn').on('click', note.openShareNote);
    $('#modal-backdrop').on('click', note.closeShareNote);

    state.md = new markdownit({
        html: true,
        linkify: true,
        breaks: true
    });

    if ($('#noteDate')) {
        $('#noteDate').datepicker();
    }

    if ($('#query')) {
        document.querySelector('#query').addEventListener('keyup', function (event) {
            if (event.key == "Enter") {
                search();
            }
        });
    }
    
    // Assuming 'to' and 'saveInterval' are declared globally elsewhere in your script
    if (typeof state.to === 'undefined' || !state.to) {
        state.to = setTimeout(note.saveNote, state.saveInterval);
    }
}

/**
 * Fetches data from '/js/data.json', assigns it to BOOKS, and handles errors.
 *
 * @return {void}
 */
export function setBooks() {
    fetch('js/data.json')
        .then((res) => {
            if (!res.ok) {
                throw new Error('HTTP Error: Status: ${res.status}');
            }
            return res.json();
        })
        .then((data) => {
            state.BOOKS = data;
        })
        .catch((error) => {
            console.log(error);
        })
}

/**
 * Opens the reference with the option to close the sidebar.
 */
export function openRef(e) {
    document.querySelector('#open-ref').classList.add('active');
    document.querySelector('#mobile-open-ref').classList.add('active');

    let refQuery = document.querySelector('#refQuery');
    refQuery.style.display = 'block';

    let closeSidebar = false;
    if(typeof e.currentTarget.closeSidebar !== 'undefined') {
        closeSidebar = e.currentTarget.closeSidebar;
    }

    if (closeSidebar && !document.querySelector('.container').classList.contains('sidebar-collapsed')) {
        document.querySelector('.toggle').click();
    }

    let ref = document.querySelector('#ref-text');
    refQuery.style.left = ref.offsetLeft + 'px';
    refQuery.style.top = ref.offsetTop + 'px';
}

/**
 * Closes the reference query and resets the reference search form.
 *
 * @return {void} This function does not return anything.
 */
export function closeRef() {
    document.querySelector('#referenceSearch').value = '';
    document.querySelector('#referenceSearch').style.display = '';
    document.querySelector('#referenceType').value = '';
    document.querySelector('#referenceBook').value = '';
    document.querySelector('#referenceBook').style.display = 'none';
    document.querySelector('#chapter-range').innerText = '';
    document.querySelector('#verse-range').innerText = '';

    document.querySelector('#refQuery').style.display = 'none';
    document.querySelector('#open-ref').classList.remove('active');
    document.querySelector('#mobile-open-ref').classList.remove('active');
}

/**
 * A function to create a button element with the specified title and event listeners for click and double click actions.
 *
 * @param {string} title - The title to be displayed on the button.
 * @return {Element} The created button element.
 */
export function makeButton(title) {
    var btn = document.createElement('button');
    btn.innerText = title;
    btn.class = 'button';
    btn.style = 'line-height:normal;'
    btn.addEventListener('click', function () {
        removeActiveRef();
        document.querySelector('#ref-text').innerHTML = state.md.render(state.references[title]);
        this.classList.add('active');
        note.findRefLinks();
    });

    btn.addEventListener('dblclick', function () {
        document.querySelector('#ref-text').innerHTML = '';
        delete state.references[title];
        var list = this.parentElement;
        list.remove();
        state.saved = false;
        state.textDirty = true;
        note.saveNote();
    });

    removeActiveRef();
    btn.classList.add('active');

    return btn;
}

/**
 * Removes the 'active' class from all elements with the class 'active'.
 *
 * @return {void} This function does not return a value.
 */
export function removeActiveRef() {
    tabs = document.querySelectorAll('#ref-list .active');
    for (var t in tabs) {
        if (isFinite(parseInt(t))) {
            tabs[t].classList.remove('active');
        }
    }
}

/**
 * Generates a random UUIDv4 string.
 *
 * @return {string} The generated UUIDv4 string.
 */
export function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
        .replace(/[xy]/g, function (c) {
            const r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
}

/**
 * Searches for notes based on the query entered in the search field.
 * Sends a POST request to the '/search' endpoint with the query as a JSON payload.
 * Updates the '#old-notes' element with the search results.
 *
 * @return {Promise} A Promise that resolves with the search results.
 */
export function search() {
    query = document.querySelector('#query').value;
    fetch('/search', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'query': query
        })
    })
        .then(response => response.json())
        .then(results => {
            var oldNotes = document.querySelector('#old-notes');
            oldNotes.innerHTML = '';
            for (var n in results) {
                var link = document.createElement('a');
                link.href = '#';
                link.setAttribute('onclick', "note.retrieveNote('" + results[n].id + "');note.openNote();");
                link.innerHTML = results[n].title;

                var p = document.createElement('p');
                p.innerHTML = results[n].passage;

                var article = document.createElement('article');
                article.appendChild(link);
                article.appendChild(p);

                oldNotes.append(article);
            }
        });
}

/**
 * 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';
}
