import {Equipment} from "../documents/equipment.mjs";

const {
    ApplicationV2,
    HandlebarsApplicationMixin
} = foundry.applications.api

export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) {

    static DEFAULT_OPTIONS = {
        classes: ['dsa41', 'dialog', 'item-browser'],
        tag: "form",
        form: {
            submitOnChange: true,
            closeOnSubmit: false,
            handler: ItemBrowserDialog.#onSubmitForm
        },
        position: {
            width: 640,
            height: 480
        },
        window: {
            resizable: true,
            title: "Gegenstände Browser"
        },
        actions: {
            select: ItemBrowserDialog.#selectItem,
            buy: ItemBrowserDialog.#buyItem
        }
    }

    static PARTS = {
        form: {
            template: 'systems/DSA_4-1/templates/dialog/item-browser-dialog.hbs',
        }
    }

    /**
     * @type {Actor}
     * @private
     */
    _actor = null
    /**
     *
     * @type {[Equipment]}
     * @private
     */
    _items = []
    _selectedItem = null
    filter_price_lower = 0
    filter_price_upper = 0
    filter_weight_lower = 0
    filter_weight_upper = 0
    filter_name = ""
    filter_category = ""

    constructor(actor) {
        super();
        this._actor = actor
        this._items = []
        this._selectedItem = null
    }

    static async #onSubmitForm(event, form, formData) {
        event.preventDefault()
        this.filter_price_lower = formData.object.filter_price_lower
        this.filter_price_upper = formData.object.filter_price_upper
        this.filter_weight_lower = formData.object.filter_weight_lower
        this.filter_weight_upper = formData.object.filter_weight_upper
        this.filter_name = formData.object.filter_name
        this.filter_category = formData.object.filter_category

        this.render({parts: ["form"]})
    }

    static async #selectItem(event, target) {
        const {itemId} = target.dataset
        const selectedItem = this._items.find(item => item.uuid === itemId)

        this._items?.forEach((item) => {
            item.selected = item.uuid === itemId
        })

        if (selectedItem) {
            this._selectedItem = selectedItem
        }
        this.render({parts: ["form"]})
    }

    static async #buyItem(event, target) {
        if (this._actor && this._selectedItem) {
            const canBuy = await this._actor.reduceWealth(this._selectedItem.price)
            if (canBuy) {
                const document = await foundry.utils.fromUuid(this._selectedItem.uuid)
                if (document) {
                    await this._actor.createEmbeddedDocuments("Item", [document])
                    ui.notifications.info(this._selectedItem.name + " wurde von " + this._actor.name + " gekauft")
                }
            } else {
                ui.notifications.error(this._selectedItem.name + " ist zu teuer für " + this._actor.name)
            }


        }
    }

    _canDragDrop(event, options) {
        return game.user.isGM
    }

    _canDrag(event, options) {
        return true
    }

    /**
     * An event that occurs when a drag workflow begins for a draggable item on the sheet.
     * @param {DragEvent} event       The initiating drag start event
     * @returns {Promise<void>}
     * @protected
     */
    async _onDragStart(event) {
        const target = event.currentTarget;
        let dragData;

        if (target.dataset.itemId) {
            dragData = {
                type: "Item",
                uuid: target.dataset.itemId
            }
        }

        // Set data transfer
        if (!dragData) return;
        event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
    }

    async _prepareContext(options) {
        const context = await super._prepareContext(options)
        context.categories = {
            "": "",
            "Gegenstand": "Gegenstand",
            "Nahkampfwaffe": "Nahkampfwaffe",
            "Fernkampfwaffe": "Fernkampfwaffe",
            "Munition": "Munition",
            "Währung": "Währung"
        }
        context.filterName = this.filter_name
        context.filterCategory = this.filter_category
        context.filter_price_lower = this.filter_price_lower ?? this._minPrice
        context.filter_price_upper = this.filter_price_upper ?? this._maxPrice
        context.filter_weight_lower = this.filter_weight_lower ?? this._minWeight
        context.filter_weight_upper = this.filter_weight_upper ?? this._maxWeight
        context.price_lower = this._minPrice
        context.price_upper = this._maxPrice
        context.weight_lower = this._minWeight
        context.weight_upper = this._maxWeight
        context.hasSelectedItem = this._selectedItem != null

        context.items = this._items
            ?.filter(p => p.name.toLowerCase().indexOf(context.filterName.toLowerCase()) !== -1 || context.filterName === "")
            ?.filter(p => p.category.indexOf(context.filterCategory) !== -1 || context.filterCategory === "")

        if (context.filter_price_lower !== context.filter_price_upper) {
            context.items = context.items?.filter(p => Number(context.filter_price_lower) <= p.price && p.price <= Number(context.filter_price_upper))
        }
        if (context.filter_price_lower !== context.filter_price_upper) {
            context.items = context.items?.filter(p => Number(context.filter_weight_lower) <= p.weight && p.weight <= Number(context.filter_weight_upper))
        }

        return context
    }

    #updateProgress(compendiumName, current, max) {
        if (compendiumName && current && max) {
            this.element.querySelector('.progress').style.display = 'block';
            this.element.querySelector('.progress .fill').style.width = (current / max * 100) + "%";
            this.element.querySelector('.progress .text').textContent = game.i18n.format("ITEM_BROWSER.progress", {
                compendium: compendiumName,
                current: current,
                max: max
            })

        } else {
            this.element.querySelector('.progress').style.display = 'none';
        }
    }

    async _onRender(context, options) {

        if (this._items.length === 0) {
            const compendia = [
                game.packs.get('DSA_4-1.Armor'),
                game.packs.get('DSA_4-1.Weapons'),
                game.packs.get('DSA_4-1.Ammunition'),
                game.packs.get('DSA_4-1.Items')
            ]

            let totalEntries = compendia.reduce((p, c) => p + c.index.size, 0)
            let parsedEntries = 0
            let currentCompendiumName = ""

            for (const c of compendia) {
                const it = await c.getDocuments()
                currentCompendiumName = c.metadata.label
                it.forEach((item) => {
                    const uuid = item.uuid
                    const e = new Equipment(item)
                    this._items.push({
                        img: item.img,
                        uuid,
                        type: item.type,
                        name: item.name,
                        price: e.system.price,
                        weight: e.system.weight,
                        category: e.system.category.join(", "),
                        selected: false,
                    })

                    parsedEntries += 1
                    this.#updateProgress(currentCompendiumName, parsedEntries, totalEntries)
                })
            }
            this._minPrice = Math.min(...this._items.map(item => item.price))
            this._maxPrice = Math.max(...this._items.map(item => item.price))

            this._minWeight = Math.min(...this._items.map(item => item.weight))
            this._maxWeight = Math.max(...this._items.map(item => item.weight))


            this.#updateProgress()
            this.render({parts: ["form"]})
        }


        new foundry.applications.ux.DragDrop.implementation({
            dropSelector: ".window-content",
            dragSelector: ".item",
            permissions: {
                drag: this._canDrag.bind(this)
            },
            callbacks: {
                dragstart: this._onDragStart.bind(this),
            }
        }).bind(this.element)
    }
}