import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
import { world } from '@minecraft/server';
import { dimensions } from './index';


const colorNames = ['§4Dark Red§r', '§mMahogony Red§r', '§cRed§r', '§6Gold§r', '§pDandelion§r', '§gHoney§r', '§eYellow§r', '§2Dark Green§r', '§qForest Green§r', '§aLime Green§r', '§bAqua§r', '§3Dark Aqua§r', '§sCadet Blue§r', '§tTeal§r', '§1Dark Blue§r', '§9Grape§r', '§dLight Purple§r', '§uDark Lavender§r', '§5Dark Purple§r', '§nBrown§r', '§fWhite§r', '§hOff White§r', '§7Gray§r', '§8Dark Gray§r', '§jCharcoal§r', '§0Black§r']
const colorCodes = ['§4', '§m', '§c', '§6', '§p', '§g', '§e', '§2', "§q", '§a', '§b', '§3', '§s', '§t', '§9', '§1', '§d', '§u', '§5', '§n', '§f', '§h', '§7', '§8', '§j', '§0'];

function menuReject(viewer, reason, nextMenu) {
    viewer.playSound('note.bass');
    nextMenu(viewer, reason);
};


export function showMenu(viewer, error) {
    const ui = new ActionFormData()
        .title('Floating Text Menu')
        .body(error ?? '')
        .button('New Floating Text', 'textures/ui/book_addtextpage_default')
        .button('New Floating Scoreboard', 'textures/ui/book_addpicture_default')
        .button('Edit Loaded Texts', 'textures/ui/icon_book_writable');

    ui.show(viewer).then(({ selection, canceled }) => {
        if (!canceled) switch (selection) {
            case 0: newText(viewer); break;
            case 1: newScoreboard(viewer); break;
            case 2: showTexts(viewer); break;
        }
    })
};


function newText(viewer) {
    const pos = viewer.location;
    const ui = new ModalFormData()
        .title('New Floating Text')
        .textField('Text to Display', 'Text')
        .textField('Text Posistion', 'Coordiates X Y Z', [pos.x.toFixed(2), pos.y.toFixed(2), pos.z.toFixed(2)].join(' '));

    ui.show(viewer).then(({ formValues, canceled }) => {
        if (canceled) return;
        const xzy = formValues[1].trim().split(' ', 3).map(v => Number(v));
        viewer.dimension.spawnEntity('monkey:floatingtext<text>', { x: xzy[0], y: xzy[1] - 0.58, z: xzy[2] })
            .nameTag = formValues[0] == '' ? 'Floating Text' : formValues[0].replace(/\\n/g, '\n');
    })
};


function newScoreboard(viewer) {
    const pos = viewer.location;
    const objectiveIDs = world.scoreboard.getObjectives().map(o => o.id); // Try to optimize this const.
    if (objectiveIDs.length == 0) { menuReject(viewer, '§cTo add scoreboards, please create a scoreboard objective. ]:<', showMenu); return };

    const ui = new ModalFormData()
        .title('New Floating Scoreboard')
        .dropdown('Scoreboard Objective to Display', objectiveIDs, 0)
        .textField('Scoreboard Position', 'Coordiates X Y Z', [pos.x.toFixed(2), pos.y.toFixed(2), pos.z.toFixed(2)].join(' '))
        .dropdown('Scores Organization', ['ascending', 'descending'], 1)
        .toggle('Enumerate Players', true)
        .dropdown('Enumeration Color', colorNames, 3)
        .dropdown('Player Name Color', colorNames, 20)
        .dropdown('Score Color', colorNames, 2)
        .slider('Amount of listed Players', 1, 15, 1, 8);

    ui.show(viewer).then(({ formValues, canceled }) => {
        if (canceled) return;
        const xzy = formValues[1].trim().split(' ', 3).map(v => Number(v));
        const entity = viewer.dimension.spawnEntity('monkey:floatingtext<scoreboard>', { x: xzy[0], y: xzy[1] - 0.58, z: xzy[2] });
        entity.setDynamicProperty('scoreboardinfo', JSON.stringify([
            objectiveIDs[formValues[0]],
            formValues[2],
            formValues[3],
            colorCodes[formValues[4]],
            colorCodes[formValues[5]],
            colorCodes[formValues[6]],
            formValues[7]
        ]));
        entity.nameTag = 'LOADING...';
    })
};



function showTexts(viewer) {
    const foundEntities = [];
    for (const dimension of dimensions) dimension.getEntities({ type: 'monkey:floatingtext', families: ['inanimate'] }).forEach(e => foundEntities.push(e));
    if (foundEntities.length == 0) { menuReject(viewer, "§cTry again later when you have active floating text! ^-^", showMenu); return };
    const ui = new ActionFormData()
        .title('Edit Nearby Texts')
        .body('Note: Only texts that are in loaded chunks will show up.');
    foundEntities.forEach(entity => {
        entity.isScoreboard = entity.matches({ families: ['scoreboard'] });
        ui.button(entity.nameTag.replace(/\n.+/g, '') + (entity.isScoreboard ? '§r\n§8[Scoreboard]' : '§r\n§8[Text]'))
    });

    ui.show(viewer).then(({ selection, canceled }) => {
        if (canceled) return;
        const entity = foundEntities[selection];
        if (entity.isScoreboard) editScoreboard(viewer, entity);
        else editText(viewer, entity);

    })
};


function editText(viewer, entity) {
    const pos = entity.location;
    const ui = new ModalFormData()
        .title(entity.nameTag.replace(/\n.+/g, ''))
        .textField('Text to Display', 'Text', entity.nameTag.replace(/\n/g, '\\n'))
        .textField('Text Posistion', 'Coordiates X Y Z', [pos.x.toFixed(2), Number(pos.y + 0.58).toFixed(2), pos.z.toFixed(2)].join(' '))
        .toggle('§cDelete Floating Text?§r', false);

    ui.show(viewer).then(({ formValues, canceled }) => {
        if (canceled) return;
        if (formValues[2]) { entity.remove(); return }
        const xzy = formValues[1].trim().split(' ', 3).map(v => Number(v));
        entity.nameTag = formValues[0] == '' ? 'Floating Text' : formValues[0].replace(/\\n/g, '\n');
        entity.teleport({ x: xzy[0], y: xzy[1] - 0.58, z: xzy[2] });
    })
};


function editScoreboard(viewer, entity) {
    const pos = entity.location;
    const objectiveIDs = world.scoreboard.getObjectives().map(o => o.id);
    const info = JSON.parse(entity.getDynamicProperty('scoreboardinfo'));
    const ui = new ModalFormData()
        .title(entity.nameTag.replace(/\n.+/g, ''))
        .dropdown('Scoreboard Objective to Display', objectiveIDs, objectiveIDs.indexOf(info[0]))
        .textField('Scoreboard Position', 'Coordiates X Y Z', [pos.x.toFixed(2), Number(pos.y + 0.58).toFixed(2), pos.z.toFixed(2)].join(' '))
        .dropdown('Scores Organization', ['ascending', 'descending'], info[1])
        .toggle('Enumerate Players', info[2])
        .dropdown('Enumeration Color', colorNames, colorCodes.indexOf(info[3]))
        .dropdown('Player Name Color', colorNames, colorCodes.indexOf(info[4]))
        .dropdown('Score Color', colorNames, colorCodes.indexOf(info[5]))
        .slider('Ammount of listed Players', 1, 15, 1, info[6])
        .toggle('§cDelete Floating Text?§r', false);

    ui.show(viewer).then(({ formValues, canceled }) => {
        if (canceled) return;
        if (formValues[8]) { entity.remove(); return }
        const xzy = formValues[1].trim().split(' ', 3).map(v => Number(v));
        entity.nameTag = 'LOADING...';
        entity.setDynamicProperty('scoreboardinfo', JSON.stringify([
            objectiveIDs[formValues[0]],
            formValues[2],
            formValues[3],
            colorCodes[formValues[4]],
            colorCodes[formValues[5]],
            colorCodes[formValues[6]],
            formValues[7]
        ]));
        entity.teleport({ x: xzy[0], y: xzy[1] - 0.58, z: xzy[2] });
    })
};