/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.velocitycore.inventory;

import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.network.packets.server.CloseInventoryPacket;
import de.steamwar.network.packets.server.InventoryPacket;
import de.steamwar.velocitycore.network.NetworkSender;
import de.steamwar.velocitycore.network.handlers.InventoryCallbackHandler;
import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;

public class SWInventory {

    private final Map<Integer, SWItem> itemMap = new HashMap<>();
    private final Chatter player;
    private final int size;
    private final Message title;
    @Setter
    private InvCallback close;
    @Getter
    @Setter
    private boolean next = false;

    private final AtomicBoolean processingClick = new AtomicBoolean();

    public SWInventory(PlayerChatter player, int size, Message title) {
        InventoryCallbackHandler.inventoryHashMap.put(player.user().getId(), this);
        this.player = player;
        this.size = size;
        this.title = title;
    }

    public void addItem(int pos, SWItem item, InvCallback callback) {
        item.setCallback(callback);
        addItem(pos, item);
    }

    public void addItem(int pos, SWItem item) {
        itemMap.put(pos, item);
    }

    public void setCallback(int pos, InvCallback callback) {
        itemMap.get(pos).setCallback(callback);
    }

    public void handleCallback(InvCallback.ClickType type, int pos) {
        if (processingClick.compareAndSet(false, true)) {
            itemMap.get(pos).getCallback().clicked(type);
            processingClick.set(false);
        }
    }

    public void handleClose() {
        if (processingClick.compareAndSet(false, true)) {
            InventoryCallbackHandler.inventoryHashMap.remove(player.user().getId(), this);
            if (close != null) close.clicked(null);
            processingClick.set(false);
        }
    }

    public void open() {
        InventoryPacket inv = new InventoryPacket(player.parseToLegacy(title), player.user().getId(), size, map(itemMap, (integer, swItem) -> swItem.writeToString(player, integer).toString()));
        player.withPlayer(p -> NetworkSender.send(p, inv));
    }

    private static <T, K, J> Map<T, J> map(Map<T, K> map, BiFunction<T, K, J> function) {
        Map<T, J> result = new HashMap<>();
        map.forEach((key, value) -> result.put(key, function.apply(key, value)));
        return result;
    }

    public void close() {
        close(player);
    }

    public static void close(Chatter player) {
        player.withPlayer(p -> NetworkSender.send(p, new CloseInventoryPacket(player.user().getId())));
    }
}
