const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets

export class MerchantSheet extends HandlebarsApplicationMixin(ActorSheetV2) {

    /** @inheritDoc */
    static DEFAULT_OPTIONS = {
        position: {width: 520, height: 480},
        classes: ['dsa41', 'sheet', 'actor', 'merchant'],
        tag: 'form',
        dragDrop: [{
            dropSelector: '.tab.inventory.active'
        }],
        form: {
            submitOnChange: true,
            closeOnSubmit: false,
            handler: MerchantSheet.#onSubmitForm
        },
        window: {
            resizable: true,
        },
        actions: {
            buy: MerchantSheet.#buyWare,
            editItem: MerchantSheet.#openEmbeddedDocument,
            editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage,
            editServiceImage: MerchantSheet.#editServiceImage,
            editNewServiceImage: MerchantSheet.#editNewServiceImage,
            addNewService: MerchantSheet.#addNewService,
            removeService: MerchantSheet.#removeService,
        }
    }

    static TABS = {
        sheet: {
            tabs: [
                {id: 'goods', group: 'sheet', label: 'Waren'},
                {id: 'services', group: 'sheet', label: 'Dienstleistungen'},
                // Meta is added via GM permission
            ],
            initial: 'goods'
        }
    }

    /** @inheritDoc */
    static PARTS = {
        form: {
            template: `systems/DSA_4-1/templates/actor/merchant/main-sheet.hbs`
        },
        goods: {
            template: `systems/DSA_4-1/templates/actor/merchant/tab-goods.hbs`
        },
        services: {
            template: `systems/DSA_4-1/templates/actor/merchant/tab-services.hbs`
        },
        meta: {
            template: `systems/DSA_4-1/templates/actor/merchant/tab-meta.hbs`
        }
    }

    constructor(options = {}) {
        super(options);
    }

    _configureRenderOptions(options) {
        super._configureRenderOptions(options)

        if (options.window) {
            options.window.title = this.document.name
        }

        return options
    }

    /**
     * Handle form submission
     * @this {AdvantageSheet}
     * @param {SubmitEvent} event
     * @param {HTMLFormElement} form
     * @param {FormDataExtended} formData
     */
    static async #onSubmitForm(event, form, formData) {
        event.preventDefault()
        await this.document.update(formData.object) // Note: formData.object
    }

    static async #buyWare(event, target) {

        const {itemId} = target.dataset
        const item = this.document.items.get(itemId)

        let selections = ''
        game.actors.filter(p => p.isOwner && p.type === "Character").forEach(actor => {
            selections += `<option value=${actor.id}>${actor.name}</option>`
        })

        const actorId = await foundry.applications.api.DialogV2.prompt({
            window: {title: `${item.name} kaufen mit wem?`},
            content: `<select name="actor">${selections}</select>`,
            ok: {
                label: `Kaufen`,
                callback: (event, button, dialog) => button.form.elements.actor.value
            }
        });

        if (actorId) { // ignore the following when dialog was cancelled
            const actor = game.actors.get(actorId)
            const canBuy = await actor.reduceWealth(item.system.price)
            if (canBuy) { // returns false when the wealth cant be reduced sufficiently
                actor.createEmbeddedDocuments('Item', [item]).then(documents => {
                    documents[0].update({'system.quantity': 1})
                })

                game.DSA41.socket.executeAsGM("buyFromLootTable", this.document.id, item.id)
                ChatMessage.create({
                    user: game.user._id,
                    speaker: {actor},
                    content: `hat ${item.name} für ${game.DSA41.displayCurrency(item.system.price)} gekauft`,
                    type: CONST.CHAT_MESSAGE_TYPES.IC
                })
            } else {
                ui.notifications.error(item.name + " ist zu teuer für " + actor.name)
            }
        }

    }

    /**
     *
     * @param {MouseEvent} event
     */
    static #openEmbeddedDocument(event) {
        let dataset = event.target.dataset
        if (!dataset.itemId && !dataset.id) {
            dataset = event.target.parentElement.dataset
        }
        const id = dataset.itemId ?? dataset.id

        if (this.document.isOwner) { // only shop owner can change stock and price
            this.document.items.get(id).sheet.render(true)
        }
    }

    static async #removeService(event, target) {
        const {rowId} = target.dataset;

        const services = this.document.services

        services.splice(rowId, 1)

        this.document.update({"system.services": services})
    }

    static async #addNewService(event, target) {
        event.preventDefault()

        const fieldset = this.element.querySelector('details')
        const image = fieldset.querySelector('img').src
        const name = fieldset.querySelector('input[name="new_name"]').value
        const price = fieldset.querySelector('input[name="new_price"]').value
        const availability = fieldset.querySelector('input[name="new_availability"]').value
        const description = fieldset.querySelector('prose-mirror').value

        if (name && price) {
            let services = this.document.system.services
            services.push({
                image,
                name,
                price,
                availability,
                description
            })

            this.document.update({"system.services": services}).then(e => {
                this.element.reset()
            })


        }

        return false
    }


    static async #editNewServiceImage(event, target) {
        const field = target.dataset.field || "img"
        const current = foundry.utils.getProperty(this.document, field)

        const fp = new foundry.applications.apps.FilePicker({
            type: "image",
            current: current,
            callback: (path) => {
                target.src = path
            }
        })

        fp.render(true)
    }

    static async #editServiceImage(event, target) {
        const field = target.dataset.field || "img"
        const current = foundry.utils.getProperty(this.document, field)

        const fp = new foundry.applications.apps.FilePicker({
            type: "image",
            current: current,
            callback: (path) => {
                target.src = path
                //foundry.utils.setProperty(this.document, field, path)
                target.parentElement.querySelector(`input[name="${field}"][type="hidden"]`).value = path
                this.element.submit()
            }
        })

        fp.render(true)
    }


    /**
     * Handle changing a Document's image.
     * @param {MouseEvent} event  The click event.
     * @returns {Promise<FilePicker>}
     * @protected
     */

    /*
    static _onEditImage(event) {
        const attr = event.currentTarget.dataset.edit;
        const current = foundry.utils.getProperty(this.object, attr);
        const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {};
        const fp = new FilePicker.implementation({
            current,
            type: "image",
            redirectToRoot: img ? [img] : [],
            callback: path => {
                event.target.src = path;
                event.target.dataset.edit
                this.document.update({'image': path})

            },
            top: this.position.top + 40,
            left: this.position.left + 10
        });
        return fp.browse();
    }*/

    _getTabsConfig(group) {
        const tabs = foundry.utils.deepClone(super._getTabsConfig(group))

        // Modify tabs based on document properties
        if (game.user.isGM) {
            tabs.tabs.push({id: "meta", group: "sheet", label: "Meta"})
        }

        return tabs
    }

    /** @override */
    async _prepareContext(options) {
        const context = await super._prepareContext(options)

        context.name = this.document.name
        context.image = this.document.img
        context.description = this.document.system.description
        context.goods = this.document.itemTypes["Equipment"] ?? []
        context.services = this.document.system.services
        context.isOwner = this.document.isOwner

        return context
    }

    /**
     * Actions performed after any render of the Application.
     * Post-render steps are not awaited by the render process.
     * @param {ApplicationRenderContext} context      Prepared context data
     * @param {RenderOptions} options                 Provided render options
     * @protected
     */
    _onRender(context, options) {

        new foundry.applications.ux.DragDrop.implementation({
            dropSelector: ".window-content",
            permissions: {
                drop: this._canDragDrop.bind(this)
            },
            callbacks: {
                drop: this._onDrop.bind(this)
            }
        }).bind(this.element);
    }

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

    async _onDrop(event) {
        const data = TextEditor.implementation.getDragEventData(event);
        const actor = this.actor;
        const allowed = Hooks.call("dropActorSheetData", actor, this, data);
        if (allowed === false) return;

        // Dropped Documents
        const documentClass = foundry.utils.getDocumentClass(data.type);
        if (documentClass) {
            const document = await documentClass.fromDropData(data);

            if (document.type === "Equipment") {
                // No duplication by moving items from one actor to another
                if (document.parent && document.parent !== this.actor) {
                    document.parent.items.get(document._id).delete()
                }

                await this._onDropDocument(event, document);
            }
        }
    }

}