/*
 *   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.misslewars.scripts.utils;

import com.google.gson.JsonObject;
import de.steamwar.misslewars.scripts.RunnableScriptEvent;
import org.bukkit.entity.*;

import static de.steamwar.misslewars.scripts.utils.JsonUtils.*;

public class EntityUtils {

    private EntityUtils() {
        throw new IllegalStateException("Utility class");
    }

    public static void setEntityOptions(Entity entity, JsonObject jsonObject) {
        getDouble(jsonObject, "velocity", aDouble -> entity.setVelocity(entity.getVelocity().multiply(aDouble)));
        getBoolean(jsonObject, "glowing", entity::setGlowing);
        getBoolean(jsonObject, "gravity", entity::setGravity);
    }

    public static void setProjectileOptions(Projectile projectile, JsonObject jsonObject) {
        setEntityOptions(projectile, jsonObject);
    }

    public static void setExplosiveOptions(Explosive explosive, JsonObject jsonObject) {
        getFloat(jsonObject, "yield", explosive::setYield);
        getBoolean(jsonObject, "incendiary", explosive::setIsIncendiary);
        setEntityOptions(explosive, jsonObject);
    }

    public static void setFireballOptions(Fireball fireball, JsonObject jsonObject) {
        setProjectileOptions(fireball, jsonObject);
        setExplosiveOptions(fireball, jsonObject);
    }

    public static void setTNTPrimedOptions(TNTPrimed tntPrimed, JsonObject jsonObject) {
        getInt(jsonObject, "fuse", tntPrimed::setFuseTicks);
        setExplosiveOptions(tntPrimed, jsonObject);
    }

    public enum EntityType {
        Projectile,
        Normal
    }

    public static ScriptShortcut getEntity(String name, EntityType entityType) {
        switch (name.toLowerCase()) {
            case "tntprimed":
                if (entityType != EntityType.Normal) return null;
                return new ScriptShortcut<>(TNTPrimed.class, (jsonObject, entity, runnableScriptEvent) -> setTNTPrimedOptions(entity, jsonObject));

            case "fireball":
                return new ScriptShortcut<>(Fireball.class, (jsonObject, entity, runnableScriptEvent) -> {
                    setFireballOptions(entity, jsonObject);
                    entity.setDirection(runnableScriptEvent.getLocation().getDirection());
                });
            case "arrow":
                return new ScriptShortcut<>(Arrow.class, (jsonObject, entity, runnableScriptEvent) -> setProjectileOptions(entity, jsonObject));
            case "windcharge":
                return new ScriptShortcut<>(WindCharge.class, (jsonObject, entity, runnableScriptEvent) -> {
                    setFireballOptions(entity, jsonObject);
                    entity.setDirection(runnableScriptEvent.getLocation().getDirection());
                });
        }
        return null;
    }

    public static class ScriptShortcut<T> {

        public Class<T> entityClass;
        public TriConsumer<JsonObject, T, RunnableScriptEvent> consumer;

        public ScriptShortcut(Class<T> entityClass, TriConsumer<JsonObject, T, RunnableScriptEvent> consumer) {
            this.entityClass = entityClass;
            this.consumer = consumer;
        }

    }

    public interface TriConsumer<T, R, K> {
        void accept(T t, R r, K k);
    }

}
