import { CommandPermissionLevel, CustomCommandParamType, CustomCommandStatus, EntityComponentTypes, system } from '@minecraft/server';
import { Command } from '../classes/Commands/Command';
import { instanceCollection } from '../classes/Instance/InstanceCollection';
import { PlayerCommandOrigin } from '../classes/Commands/PlayerCommandOrigin';
import { NotAPlayerError } from '../classes/Errors/NotAPlayerError';

export class MaterialsCommand extends Command {
    constructor() {
        super({
            name: 'materials',
            description: 'construct.commands.materials',
            mandatoryParameters: [
                { name: 'instanceName', type: CustomCommandParamType.String }
            ],
            optionalParameters: [
                { name: 'missing', type: CustomCommandParamType.Boolean }
            ],
            permissionLevel: CommandPermissionLevel.Any,
            callback: (origin, instanceName, missing) => this.run(origin, instanceName, missing)
        });
    }

    run(origin, instanceName, missing) {
        const instance = instanceCollection.get(instanceName);
        const onlyMissing = missing === true;
        if (onlyMissing)
            this.assertIsPlayer(origin);
        const headerKey = onlyMissing ? 'construct.commands.materials.headerMissing' : 'construct.commands.materials.headerAll';
        const rawtext = [
            { translate: headerKey, with: [instanceName] },
            { text: '\n' }
        ];
        const list = this.getMaterialList(origin, instance, onlyMissing);
        if (!list.rawtext || list.rawtext.length === 0)
            rawtext.push({ translate: 'construct.commands.materials.empty' });
        else
            rawtext.push(list);
        origin.sendMessage({ rawtext });
        return { status: CustomCommandStatus.Success };
    }

    assertIsPlayer(origin) {
        if (!(origin instanceof PlayerCommandOrigin))
            throw new NotAPlayerError();
    }

    getMaterialList(origin, instance, onlyMissing) {
        const materials = instance.getActiveMaterials();
        let container;
        if (onlyMissing) {
            const player = origin.getSource();
            const inventoryComponent = player?.getComponent(EntityComponentTypes.Inventory);
            container = inventoryComponent?.container;
        }
        const materialsMap = onlyMissing ? materials.getMaterialsDifference(container) : void 0;
        return materials.formatString(materialsMap);
    }
}

export const materialsCommand = new MaterialsCommand();
