(() => {
const { clipboard } = require('electron')

const CatalogManager = require('./assets/js/catalogmanager')
const ConfigManager = require('./assets/js/configmanager')
const ProfileAssetManager = require('./assets/js/profileassetmanager')
const ServerRuntime = require('./assets/js/serverruntime')
const { DistroAPI } = require('./assets/js/distromanager')

const libraryList = document.getElementById('libraryList')
const libraryEmptyState = document.getElementById('libraryEmptyState')

function renderLibraryEmptyState(isEmpty){
    libraryEmptyState.style.display = isEmpty ? 'flex' : 'none'
}

function createBadge(text){
    const badge = document.createElement('span')
    badge.className = 'launcherBadge'
    badge.textContent = text
    return badge
}

function describeProfileKind(kind){
    switch(kind){
        case 'map':
            return '맵'
        case 'server-pack':
            return '서버팩'
        case 'modpack':
        default:
            return '모드팩'
    }
}

function createParagraph(className, text){
    const element = document.createElement('p')
    element.className = className
    element.textContent = text
    return element
}

function createInfoLine(label, value){
    const line = document.createElement('div')
    line.className = 'launcherInfoLine'

    const labelElement = document.createElement('span')
    labelElement.className = 'launcherInfoLabel'
    labelElement.textContent = label

    const valueElement = document.createElement('span')
    valueElement.className = 'launcherInfoValue'
    valueElement.textContent = value

    line.appendChild(labelElement)
    line.appendChild(valueElement)
    return line
}

function showLibraryMessage(title, message){
    if(typeof setOverlayContent === 'function'){
        setOverlayContent(title, message, '확인')
        setOverlayHandler(() => toggleOverlay(false))
        toggleOverlay(true)
    }
}

function describeAssetState(profile){
    const state = ConfigManager.getLibraryProfileAssetState(profile.id)

    if(profile.kind === 'map'){
        if(state.worldInstalledAt){
            return `맵 설치 완료 · ${profile.worldDirectoryName}`
        }
        if(profile.worldArchiveUrl){
            return '맵 아카이브 준비 필요'
        }
    }

    if(profile.kind === 'server-pack'){
        if(state.serverBundleInstalledAt){
            return '서버 번들 설치 완료'
        }
        if(profile.serverBundleUrl){
            return '서버 번들 준비 필요'
        }
    }

    return '추가 자산 없음'
}

function isProfileInstalled(profile){
    const state = ConfigManager.getLibraryProfileAssetState(profile.id)

    if(profile.kind === 'map'){
        return state.prefetchedAt != null || profile.worldArchiveUrl == null
    }

    if(profile.kind === 'server-pack'){
        return state.serverBundleInstalledAt != null || state.prefetchedAt != null || profile.serverBundleUrl == null
    }

    return true
}

async function prepareProfileAssets(profile){
    try {
        await ProfileAssetManager.prefetchProfileAssets(profile)
        if(profile.kind === 'server-pack' && profile.hostReady){
            await ProfileAssetManager.ensureServerBundleInstalled(profile)
        }
        await renderLibraryView()
        showLibraryMessage('자료 준비 완료', `${profile.name} 자료를 준비했습니다.`)
    } catch (error) {
        console.error(error)
        showLibraryMessage('자료 준비 실패', '프로필 자료를 내려받거나 해제하는 중 오류가 발생했습니다.')
    }
}

async function applyProfileSelection(profile){
    CatalogManager.selectProfile(profile.id)
    CatalogManager.applyConfiguredProfile()

    const distro = await DistroAPI.refreshDistributionOrFallback()
    if(distro == null){
        throw new Error('Distribution refresh returned null.')
    }

    const currentServer = distro.getServerById(ConfigManager.getSelectedServer())
    if(currentServer == null && typeof distro.getMainServer === 'function'){
        const mainServer = distro.getMainServer()
        if(mainServer != null){
            ConfigManager.setSelectedServer(mainServer.rawServer.id)
            ConfigManager.save()
        }
    }

    onDistroRefresh(distro)
}

async function activateProfile(profile, launchNow = false){
    if(!profile.configured){
        const firstIssue = profile.launchIssues?.[0] ?? '이 프로필은 아직 실행 조건이 충족되지 않았습니다.'
        showLibraryMessage('프로필 설정 필요', firstIssue)
        return
    }

    CatalogManager.selectProfile(profile.id)
    CatalogManager.applyConfiguredProfile()
    if(typeof refreshSelectedProfileButton === 'function'){
        refreshSelectedProfileButton()
    }

    try {
        const distro = await DistroAPI.refreshDistributionOrFallback()
        if(distro == null){
            throw new Error('Distribution refresh returned null.')
        }

        const currentServer = distro.getServerById(ConfigManager.getSelectedServer())
        if(currentServer == null && typeof distro.getMainServer === 'function'){
            const mainServer = distro.getMainServer()
            if(mainServer != null){
                ConfigManager.setSelectedServer(mainServer.rawServer.id)
                ConfigManager.save()
            }
        }

        const selectedServerId = ConfigManager.getSelectedServer()
        if(selectedServerId != null){
            await ProfileAssetManager.prepareProfileForLaunch(profile, selectedServerId)
        }

        onDistroRefresh(distro)

        if(getCurrentView() === VIEWS.landing){
            if(launchNow){
                document.getElementById('launch_button').click()
            }
            return
        }

        switchView(getCurrentView(), VIEWS.landing, 250, 250, () => {}, () => {
            if(launchNow){
                document.getElementById('launch_button').click()
            }
        })
    } catch (error) {
        console.error(error)
        showLibraryMessage('프로필 로드 실패', '선택한 프로필의 distribution.json 또는 부가 자산을 불러오지 못했습니다.')
    }
}

function appendAddressOverrideField(profile, fieldGroup){
    if(!profile.allowCustomServerAddress){
        return
    }

    const label = document.createElement('label')
    label.className = 'launcherFieldLabel'
    label.textContent = '접속 주소'

    const input = document.createElement('input')
    input.className = 'launcherFieldInput'
    input.type = 'text'
    input.placeholder = profile.defaultServerAddress || 'example.com:25565'
    input.value = ConfigManager.getLibraryServerAddressOverride(profile.id) ?? ''
    input.addEventListener('change', () => {
        CatalogManager.setServerAddressOverride(profile.id, input.value)
    })

    fieldGroup.appendChild(label)
    fieldGroup.appendChild(input)
}

function appendPublishedAddressField(profile, hostState, fieldGroup){
    if(!hostState.publishedAddress){
        return
    }

    const label = document.createElement('label')
    label.className = 'launcherFieldLabel'
    label.textContent = '호스트 공개 주소'

    const row = document.createElement('div')
    row.className = 'launcherInlineField'

    const input = document.createElement('input')
    input.className = 'launcherFieldInput'
    input.type = 'text'
    input.readOnly = true
    input.value = hostState.publishedAddress

    const copyButton = document.createElement('button')
    copyButton.className = 'launcherSecondaryButton'
    copyButton.textContent = '주소 복사'
    copyButton.addEventListener('click', () => {
        clipboard.writeText(hostState.publishedAddress)
    })

    row.appendChild(input)
    row.appendChild(copyButton)
    fieldGroup.appendChild(label)
    fieldGroup.appendChild(row)
}

async function renderLibraryView(){
    libraryList.innerHTML = ''

    try {
        const installedProfiles = await CatalogManager.getInstalledProfiles()
        const selectedProfileId = CatalogManager.getSelectedProfileId()

        renderLibraryEmptyState(installedProfiles.length === 0)

        for(const profile of installedProfiles){
            const hostState = ServerRuntime.getHostedProfileState(profile.id)
            const card = document.createElement('article')
            card.className = 'launcherCard'
            if(profile.id === selectedProfileId){
                card.setAttribute('selected', 'true')
            }

            const header = document.createElement('div')
            header.className = 'launcherCardHeader'

            const titleGroup = document.createElement('div')
            titleGroup.className = 'launcherCardTitleGroup'

            const title = document.createElement('h3')
            title.className = 'launcherCardTitle'
            title.textContent = profile.name

            const meta = document.createElement('div')
            meta.className = 'launcherCardMeta'
            meta.appendChild(createBadge(describeProfileKind(profile.kind)))
            if(profile.isCustom){
                meta.appendChild(createBadge('커스텀'))
            }
            if(profile.id === selectedProfileId){
                meta.appendChild(createBadge('선택됨'))
            }
            if(profile.kind === 'map' && profile.worldDirectoryName){
                meta.appendChild(createBadge(profile.worldDirectoryName))
            }
            if(profile.kind === 'map' && !profile.launchReady){
                meta.appendChild(createBadge('맵 설정 필요'))
            }
            if(profile.kind === 'server-pack' && !profile.hostReady){
                meta.appendChild(createBadge('호스팅 설정 필요'))
            }
            if(hostState.running){
                meta.appendChild(createBadge(hostState.tunneling ? '서버+터널' : '서버 실행 중'))
            }

            titleGroup.appendChild(title)
            titleGroup.appendChild(meta)
            header.appendChild(titleGroup)

            const description = createParagraph('launcherCardDescription', profile.description || '설명이 없습니다.')

            const actions = document.createElement('div')
            actions.className = 'launcherCardActions'

            const installButton = document.createElement('button')
            installButton.className = 'launcherSecondaryButton'
            installButton.textContent = isProfileInstalled(profile) ? '설치됨' : '설치'
            installButton.disabled = isProfileInstalled(profile) || !profile.configured
            installButton.addEventListener('click', async () => {
                await prepareProfileAssets(profile)
            })

            const selectButton = document.createElement('button')
            selectButton.className = 'launcherSecondaryButton'
            selectButton.textContent = profile.id === selectedProfileId ? '선택됨' : '선택'
            selectButton.disabled = profile.id === selectedProfileId
            selectButton.addEventListener('click', async () => {
                try {
                    await applyProfileSelection(profile)
                    if(typeof refreshSelectedProfileButton === 'function'){
                        refreshSelectedProfileButton()
                    }
                    if(typeof refreshServerStatus === 'function'){
                        refreshServerStatus(true)
                    }
                    await renderLibraryView()
                } catch (error) {
                    console.error(error)
                    showLibraryMessage('프로필 선택 실패', '선택한 프로필의 배포 정보 또는 서버 정보를 불러오지 못했습니다.')
                }
            })

            actions.appendChild(installButton)
            actions.appendChild(selectButton)

            const removeButton = document.createElement('button')
            removeButton.className = 'launcherGhostButton'
            removeButton.textContent = '제거'
            removeButton.addEventListener('click', async () => {
                ServerRuntime.stopHostedProfile(profile.id)
                CatalogManager.removeProfile(profile.id)
                if(typeof refreshSelectedProfileButton === 'function'){
                    refreshSelectedProfileButton()
                }
                if(typeof refreshServerStatus === 'function'){
                    refreshServerStatus(true)
                }
                await renderLibraryView()
                if(typeof refreshInstallView === 'function'){
                    await refreshInstallView()
                }
            })

            actions.appendChild(removeButton)

            card.appendChild(header)
            card.appendChild(description)
            card.appendChild(actions)
            libraryList.appendChild(card)
        }
    } catch (error) {
        console.error(error)
        renderLibraryEmptyState(false)
        const errorCard = document.createElement('article')
        errorCard.className = 'launcherCard'
        errorCard.innerHTML = '<h3 class="launcherCardTitle">라이브러리 로드 실패</h3><p class="launcherCardDescription">선택한 카탈로그를 읽지 못했습니다. 설치 페이지에서 카탈로그 경로를 다시 확인하세요.</p>'
        libraryList.appendChild(errorCard)
    }
}

document.getElementById('libraryBackButton').addEventListener('click', () => {
    switchView(getCurrentView(), VIEWS.landing)
})

setInterval(() => {
    if(getCurrentView() === VIEWS.library && ServerRuntime.hasRunningProfiles()){
        renderLibraryView()
    }
}, 3000)

window.refreshLibraryView = renderLibraryView
renderLibraryView()
})()
