let activeTags = []
let modifiers = []
let customModifiersGroupElement = undefined

let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
let previewImageField = document.querySelector('#preview-image')
let modifierSettingsBtn = document.querySelector('#modifier-settings-btn')
let modifierSettingsOverlay = document.querySelector('#modifier-settings-config')
let customModifiersTextBox = document.querySelector('#custom-modifiers-input')
let customModifierEntriesToolbar = document.querySelector('#editor-modifiers-entries-toolbar')

const modifierThumbnailPath = 'media/modifier-thumbnails'
const activeCardClass = 'modifier-card-active'
const CUSTOM_MODIFIERS_KEY = "customModifiers"

function createModifierCard(name, previews, removeBy) {
    const modifierCard = document.createElement('div')
    modifierCard.className = 'modifier-card'
    modifierCard.innerHTML = `
    <div class="modifier-card-overlay"></div>
    <div class="modifier-card-image-container">
        <div class="modifier-card-image-overlay">+</div>
        <p class="modifier-card-error-label"></p>
        <img onerror="this.remove()" alt="Modifier Image" class="modifier-card-image">
    </div>
    <div class="modifier-card-container">
        <div class="modifier-card-label"><p></p></div>
    </div>`

    const image = modifierCard.querySelector('.modifier-card-image')
    const errorText =  modifierCard.querySelector('.modifier-card-error-label')
    const label = modifierCard.querySelector('.modifier-card-label')

    errorText.innerText = 'No Image'

    if (typeof previews == 'object') {
        image.src = previews[0]; // portrait
        image.setAttribute('preview-type', 'portrait')
    } else {
        image.remove()
    }

    const maxLabelLength = 30
    const cardLabel = removeBy ? name.replace('by ', '') : name

    if(cardLabel.length <= maxLabelLength) {
        label.querySelector('p').innerText = cardLabel
        label.querySelector('p').dataset.fullName = name // preserve the full name
    } else {
        const tooltipText = document.createElement('span')
        tooltipText.className = 'tooltip-text'
        tooltipText.innerText = name

        label.classList.add('tooltip')
        label.appendChild(tooltipText)

        label.querySelector('p').innerText = cardLabel.substring(0, maxLabelLength) + '...'
    }

    return modifierCard
}

function createModifierGroup(modifierGroup, initiallyExpanded, removeBy) {
    const title = modifierGroup.category
    const modifiers = modifierGroup.modifiers

    const titleEl = document.createElement('h5')
    titleEl.className = 'collapsible'
    titleEl.innerText = title

    const modifiersEl = document.createElement('div')
    modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf')

    if (initiallyExpanded === true) {
        titleEl.className += ' active'
    }

    modifiers.forEach(modObj => {
        const modifierName = modObj.modifier
        const modifierPreviews = modObj?.previews?.map(preview => `${IMAGE_REGEX.test(preview.image) ? preview.image : modifierThumbnailPath + '/' + preview.path}`)

        const modifierCard = createModifierCard(modifierName, modifierPreviews, removeBy)

        if(typeof modifierCard == 'object') {
            modifiersEl.appendChild(modifierCard)
            const trimmedName = trimModifiers(modifierName)

            modifierCard.addEventListener('click', () => {
                if (activeTags.map(x => trimModifiers(x.name)).includes(trimmedName)) {
                    // remove modifier from active array
                    activeTags = activeTags.filter(x => trimModifiers(x.name) != trimmedName)
                    toggleCardState(trimmedName, false)
                } else {
                    // add modifier to active array
                    activeTags.push({
                        'name': modifierName,
                        'element': modifierCard.cloneNode(true),
                        'originElement': modifierCard,
                        'previews': modifierPreviews
                    })
                    toggleCardState(trimmedName, true)
                }

                refreshTagsList()
                document.dispatchEvent(new Event('refreshImageModifiers'))
            })
        }
    })

    let brk = document.createElement('br')
    brk.style.clear = 'both'
    modifiersEl.appendChild(brk)

    let e = document.createElement('div')
    e.appendChild(titleEl)
    e.appendChild(modifiersEl)

    editorModifierEntries.insertBefore(e, customModifierEntriesToolbar.nextSibling)

    return e
}

function trimModifiers(tag) {
    return tag.replace(/^\(+|\)+$/g, '').replace(/^\[+|\]+$/g, '')
}

async function loadModifiers() {
    try {
        let res = await fetch('/get/modifiers')
        if (res.status === 200) {
            res = await res.json()

            modifiers = res; // update global variable

            res.reverse()

            res.forEach((modifierGroup, idx) => {
                createModifierGroup(modifierGroup, idx === res.length - 1, modifierGroup === 'Artist' ? true : false) // only remove "By " for artists
            })

            createCollapsibles(editorModifierEntries)
        }
    } catch (e) {
        console.log('error fetching modifiers', e)
    }

    loadCustomModifiers()
    document.dispatchEvent(new Event('loadImageModifiers'))
}

function refreshModifiersState(newTags) {
    // clear existing modifiers
    document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
        const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
        if (activeTags.map(x => x.name).includes(modifierName)) {
            modifierCard.classList.remove(activeCardClass)
            modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
        }
    })
    activeTags = []

    // set new modifiers
    newTags.forEach(tag => {
        let found = false
        document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
            const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
            if (trimModifiers(tag) == trimModifiers(modifierName)) {
                // add modifier to active array
                if (!activeTags.map(x => x.name).includes(tag)) { // only add each tag once even if several custom modifier cards share the same tag
                    const imageModifierCard = modifierCard.cloneNode(true)
                    imageModifierCard.querySelector('.modifier-card-label p').innerText = tag
                    activeTags.push({
                        'name': modifierName,
                        'element': imageModifierCard,
                        'originElement': modifierCard
                    })
                }
                modifierCard.classList.add(activeCardClass)
                modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-'
                found = true
            }
        })
        if (found == false) { // custom tag went missing, create one here
            let modifierCard = createModifierCard(tag, undefined, false) // create a modifier card for the missing tag, no image
            
            modifierCard.addEventListener('click', () => {
                if (activeTags.map(x => x.name).includes(tag)) {
                    // remove modifier from active array
                    activeTags = activeTags.filter(x => x.name != tag)
                    modifierCard.classList.remove(activeCardClass)

                    modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
                }
                refreshTagsList()
            })

            activeTags.push({
                'name': tag,
                'element': modifierCard,
                'originElement': undefined  // no origin element for missing tags
            })
        }
    })
    refreshTagsList()
}

function refreshInactiveTags(inactiveTags) {
    // update inactive tags
    if (inactiveTags !== undefined && inactiveTags.length > 0) {
        activeTags.forEach (tag => {
            if (inactiveTags.find(element => element === tag.name) !== undefined) {
                tag.inactive = true
            }
        })
    }
    
    // update cards
    let overlays = document.querySelector('#editor-inputs-tags-list').querySelectorAll('.modifier-card-overlay')
    overlays.forEach (i => {
        let modifierName = i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText
        if (inactiveTags.find(element => element === modifierName) !== undefined) {
            i.parentElement.classList.add('modifier-toggle-inactive')
        }
    })
}

function refreshTagsList() {
    editorModifierTagsList.innerHTML = ''

    if (activeTags.length == 0) {
        editorTagsContainer.style.display = 'none'
        return
    } else {
        editorTagsContainer.style.display = 'block'
    }

    activeTags.forEach((tag, index) => {
        tag.element.querySelector('.modifier-card-image-overlay').innerText = '-'
        tag.element.classList.add('modifier-card-tiny')

        editorModifierTagsList.appendChild(tag.element)

        tag.element.addEventListener('click', () => {
            let idx = activeTags.findIndex(o => { return o.name === tag.name })            

            if (idx !== -1) {
                toggleCardState(activeTags[idx].name, false)

                activeTags.splice(idx, 1)
                refreshTagsList()
            }
            document.dispatchEvent(new Event('refreshImageModifiers'))
        })
    })

    let brk = document.createElement('br')
    brk.style.clear = 'both'
    editorModifierTagsList.appendChild(brk)
}

function toggleCardState(modifierName, makeActive) {
    document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(card => {
        const name = card.querySelector('.modifier-card-label').innerText
        if (   trimModifiers(modifierName) == trimModifiers(name)
            || trimModifiers(modifierName) == 'by ' + trimModifiers(name)) {
            if(makeActive) {
                card.classList.add(activeCardClass)
                card.querySelector('.modifier-card-image-overlay').innerText = '-'
            }
            else{
                card.classList.remove(activeCardClass)
                card.querySelector('.modifier-card-image-overlay').innerText = '+'
            }
        }
    })
}

function changePreviewImages(val) {
    const previewImages = document.querySelectorAll('.modifier-card-image-container img')

    let previewArr = []

    modifiers.map(x => x.modifiers).forEach(x => previewArr.push(...x.map(m => m.previews)))
    
    previewArr = previewArr.map(x => {
        let obj = {}

        x.forEach(preview => {
            obj[preview.name] = preview.path
        })
        
        return obj
    })

    previewImages.forEach(previewImage => {
        const currentPreviewType = previewImage.getAttribute('preview-type')
        const relativePreviewPath = previewImage.src.split(modifierThumbnailPath + '/').pop()

        const previews = previewArr.find(preview => relativePreviewPath == preview[currentPreviewType])

        if(typeof previews == 'object') {
            let preview = null

            if (val == 'portrait') {
                preview = previews.portrait
            }
            else if (val == 'landscape') {
                preview = previews.landscape
            }

            if(preview != null) {
                previewImage.src = `${modifierThumbnailPath}/${preview}`
                previewImage.setAttribute('preview-type', val)
            }
        }
    })
}

function resizeModifierCards(val) {
    const cardSizePrefix = 'modifier-card-size_'
    const modifierCardClass = 'modifier-card'

    const modifierCards = document.querySelectorAll(`.${modifierCardClass}`)
    const cardSize = n => `${cardSizePrefix}${n}`

    modifierCards.forEach(card => {
        // remove existing size classes
        const classes = card.className.split(' ').filter(c => !c.startsWith(cardSizePrefix))
        card.className = classes.join(' ').trim()

        if(val != 0) {
            card.classList.add(cardSize(val))
        }
    })
}

modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value)
previewImageField.onchange = () => changePreviewImages(previewImageField.value)

modifierSettingsBtn.addEventListener('click', function(e) {
    modifierSettingsOverlay.classList.add("active")
    e.stopPropagation()
})

function saveCustomModifiers() {
    localStorage.setItem(CUSTOM_MODIFIERS_KEY, customModifiersTextBox.value.trim())

    loadCustomModifiers()
}

function loadCustomModifiers() {
    PLUGINS['MODIFIERS_LOAD'].forEach(fn=>fn.loader.call())
}

customModifiersTextBox.addEventListener('change', saveCustomModifiers)
