package pers.neige.neigeitems.libs.bot.inker.bukkit.nbt.neigeitems.utils;

import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Item;
import org.jetbrains.annotations.Nullable;
import pers.neige.neigeitems.libs.bot.inker.bukkit.nbt.internal.annotation.CbVersion;
import pers.neige.neigeitems.ref.entity.RefCraftItem;
import pers.neige.neigeitems.ref.entity.RefEntityItem;

import java.util.UUID;

public class EntityItemUtils {
    /**
     * 1.17+ 版本起, EntityItem 内部 despawnRate 字段即表示掉落物的最大存活时长.
     * 此前版本需要从掉落物所在世界实例中获取 SpigotWorldConfig, 获取世界配置中掉落物的最大存活时长.
     */
    private static final boolean HAS_DESPAWN_RATE = CbVersion.v1_17_R1.isSupport();
    /**
     * 1.13+ 版本起, owner 和 thrower 以 UUID 形式存储, 1.12.2 版本则为 String 形式的玩家名.
     */
    private static final boolean UUID_SUPPORT = CbVersion.v1_13_R1.isSupport();
    /**
     * 1.16.3+ 版本起, Item 类提供获取和设置 owner/thrower 的方法.
     * 1.16.2 和 1.16.3 都是 v1_16_R2, 所以按 v1_16_R3 起算.
     */
    private static final boolean GET_AND_SET_SUPPORT = CbVersion.v1_16_R3.isSupport();
    /**
     * 1.20.2+ 版本起, CraftItem 类移除私有字段 item.
     * 改为通过 getHandle 方法获取对应的 ItemEntity.
     */
    private static final boolean REMOVE_CRAFTITEM_ITEM = CbVersion.v1_20_R2.isSupport();

    private static RefEntityItem getHandle(
        RefCraftItem item
    ) {
        if (REMOVE_CRAFTITEM_ITEM) {
            return item.getHandle();
        } else {
            return item.item;
        }
    }

    /**
     * 判断给定的 Item 实体是否属于 CraftItem.
     *
     * @param item 待检测物品.
     * @return 是否属于 CraftItem.
     */
    public static boolean isCraftItem(
        Item item
    ) {
        return (Object) item instanceof RefCraftItem;
    }

    /**
     * 获取掉落物实体的已存活时长(tick).
     * 若该物品不属于 CraftItem 则返回 null.
     *
     * @param item 待检测物品.
     * @return 掉落物实体的已存活时长(tick).
     */
    public static @Nullable Integer getAge(
        @NonNull Item item
    ) {
        if ((Object) item instanceof RefCraftItem) {
            return getHandle((RefCraftItem) (Object) item).age;
        }
        return null;
    }

    /**
     * 设置掉落物实体的已存活时长(tick).
     *
     * @param item 待检测物品.
     * @param age  掉落物实体的已存活时长(tick).
     */
    public static void setAge(
        @NonNull Item item,
        int age
    ) {
        if ((Object) item instanceof RefCraftItem) {
            getHandle((RefCraftItem) (Object) item).age = age;
        }
    }

    /**
     * 获取掉落物实体的最大存活时长(tick).
     *
     * @param item 待检测物品.
     * @return 掉落物实体的最大存活时长(tick).
     */
    public static int getDespawnRate(
        @NonNull Item item
    ) {
        if (HAS_DESPAWN_RATE && ((Object) item instanceof RefCraftItem)) {
            return getHandle((RefCraftItem) (Object) item).despawnRate;
        } else {
            return WorldUtils.getDespawnRate(item.getWorld());
        }
    }

    /**
     * 获取掉落物实体的拥有者(不存在或无法获取则返回 null).
     * 1.12.2 的 owner 是 String, 1.13+ 的 owner 是 UUID, 所以返回 OfflinePlayer.
     *
     * @param item 待检测物品.
     * @return 物品拥有者.
     */
    public static @Nullable OfflinePlayer getOwner(
        @NonNull Item item
    ) {
        if (GET_AND_SET_SUPPORT) {
            UUID owner = item.getOwner();
            if (owner == null) return null;
            return Bukkit.getOfflinePlayer(owner);
        } else {
            if ((Object) item instanceof RefCraftItem) {
                if (UUID_SUPPORT) {
                    UUID ownerUUID = getHandle((RefCraftItem) (Object) item).ownerUUID;
                    if (ownerUUID == null) return null;
                    return Bukkit.getOfflinePlayer(ownerUUID);
                } else {
                    String ownerName = getHandle((RefCraftItem) (Object) item).ownerName;
                    if (ownerName == null) return null;
                    return Bukkit.getOfflinePlayer(ownerName);
                }
            }
        }
        return null;
    }

    /**
     * 获取掉落物实体的拥有者玩家名(不存在或无法获取则返回 null).
     * 1.13+ 版本永远返回 null.
     *
     * @param item 待检测物品.
     * @return 物品拥有者玩家名.
     */
    public static @Nullable String getOwnerName(
        @NonNull Item item
    ) {
        if ((Object) item instanceof RefCraftItem && !UUID_SUPPORT) {
            return getHandle((RefCraftItem) (Object) item).ownerName;
        }
        return null;
    }

    /**
     * 获取掉落物实体的拥有者UUID(不存在或无法获取则返回 null).
     * 1.12.2 版本永远返回 null.
     *
     * @param item 待检测物品.
     * @return 物品拥有者UUID.
     */
    public static @Nullable UUID getOwnerUUID(
        @NonNull Item item
    ) {
        if (GET_AND_SET_SUPPORT) {
            return item.getOwner();
        } else {
            if ((Object) item instanceof RefCraftItem && UUID_SUPPORT) {
                return getHandle((RefCraftItem) (Object) item).ownerUUID;
            }
        }
        return null;
    }

    /**
     * 设置掉落物实体的拥有者.
     * 1.12.2 的 owner 是 String, 1.13+ 的 owner 是 UUID, 所以需要 OfflinePlayer.
     *
     * @param item   待设置物品.
     * @param player 物品拥有者.
     */
    public static void setOwner(
        @NonNull Item item,
        @NonNull OfflinePlayer player
    ) {
        if (GET_AND_SET_SUPPORT) {
            item.setOwner(player.getUniqueId());
        } else {
            if ((Object) item instanceof RefCraftItem) {
                if (UUID_SUPPORT) {
                    getHandle((RefCraftItem) (Object) item).ownerUUID = player.getUniqueId();
                } else {
                    getHandle((RefCraftItem) (Object) item).ownerName = player.getName();
                }
            }
        }
    }

    /**
     * 设置掉落物实体的拥有者.
     * 1.13+ 版本调用该方法将不会产生任何效果.
     *
     * @param item 待设置物品.
     * @param name 物品拥有者玩家名.
     */
    public static void setOwnerName(
        @NonNull Item item,
        @NonNull String name
    ) {
        if ((Object) item instanceof RefCraftItem && !UUID_SUPPORT) {
            getHandle((RefCraftItem) (Object) item).ownerName = name;
        }
    }

    /**
     * 设置掉落物实体的拥有者.
     * 1.12.2 版本调用该方法将不会产生任何效果.
     *
     * @param item 待设置物品.
     * @param uuid 物品拥有者UUID.
     */
    public static void setOwnerUUID(
        @NonNull Item item,
        @NonNull UUID uuid
    ) {
        if (GET_AND_SET_SUPPORT) {
            item.setOwner(uuid);
        } else {
            if ((Object) item instanceof RefCraftItem && UUID_SUPPORT) {
                getHandle((RefCraftItem) (Object) item).ownerUUID = uuid;
            }
        }
    }

    /**
     * 获取掉落物实体的丢出者(不存在或无法获取则返回 null).
     * 1.12.2 的 thrower 是 String, 1.13+ 的 thrower 是 UUID, 所以返回 OfflinePlayer.
     *
     * @param item 待检测物品.
     * @return 物品丢出者.
     */
    public static @Nullable OfflinePlayer getThrower(
        @NonNull Item item
    ) {
        if (GET_AND_SET_SUPPORT) {
            UUID thrower = item.getThrower();
            if (thrower == null) return null;
            return Bukkit.getOfflinePlayer(thrower);
        } else {
            if ((Object) item instanceof RefCraftItem) {
                if (UUID_SUPPORT) {
                    UUID throwerUUID = getHandle((RefCraftItem) (Object) item).throwerUUID;
                    if (throwerUUID == null) return null;
                    return Bukkit.getOfflinePlayer(throwerUUID);
                } else {
                    String throwerName = getHandle((RefCraftItem) (Object) item).throwerName;
                    if (throwerName == null) return null;
                    return Bukkit.getOfflinePlayer(throwerName);
                }
            }
        }
        return null;
    }

    /**
     * 获取掉落物实体的丢出者玩家名(不存在或无法获取则返回 null).
     * 1.13+ 版本永远返回 null.
     *
     * @param item 待检测物品.
     * @return 物品丢出者玩家名.
     */
    public static @Nullable String getThrowerName(
        @NonNull Item item
    ) {
        if ((Object) item instanceof RefCraftItem && !UUID_SUPPORT) {
            return getHandle((RefCraftItem) (Object) item).throwerName;
        }
        return null;
    }

    /**
     * 获取掉落物实体的丢出者UUID(不存在或无法获取则返回 null).
     * 1.12.2 版本永远返回 null.
     *
     * @param item 待检测物品.
     * @return 物品丢出者UUID.
     */
    public static @Nullable UUID getThrowerUUID(
        @NonNull Item item
    ) {
        if (GET_AND_SET_SUPPORT) {
            return item.getThrower();
        } else {
            if ((Object) item instanceof RefCraftItem && UUID_SUPPORT) {
                return getHandle((RefCraftItem) (Object) item).throwerUUID;
            }
        }
        return null;
    }

    /**
     * 设置掉落物实体的丢出者.
     * 1.12.2 的 thrower 是 String, 1.13+ 的 thrower 是 UUID, 所以需要 OfflinePlayer.
     *
     * @param item   待设置物品.
     * @param player 物品丢出者.
     */
    public static void setThrower(
        @NonNull Item item,
        @NonNull OfflinePlayer player
    ) {
        if (GET_AND_SET_SUPPORT) {
            item.setThrower(player.getUniqueId());
        } else {
            if ((Object) item instanceof RefCraftItem) {
                if (UUID_SUPPORT) {
                    getHandle((RefCraftItem) (Object) item).throwerUUID = player.getUniqueId();
                } else {
                    getHandle((RefCraftItem) (Object) item).throwerName = player.getName();
                }
            }
        }
    }

    /**
     * 设置掉落物实体的丢出者.
     * 1.13+ 版本调用该方法将不会产生任何效果.
     *
     * @param item 待设置物品.
     * @param name 物品丢出者玩家名.
     */
    public static void setThrowerName(
        @NonNull Item item,
        @NonNull String name
    ) {
        if ((Object) item instanceof RefCraftItem && !UUID_SUPPORT) {
            getHandle((RefCraftItem) (Object) item).throwerName = name;
        }
    }

    /**
     * 设置掉落物实体的丢出者.
     * 1.12.2 版本调用该方法将不会产生任何效果.
     *
     * @param item 待设置物品.
     * @param uuid 物品丢出者UUID.
     */
    public static void setThrowerUUID(
        @NonNull Item item,
        @NonNull UUID uuid
    ) {
        if (GET_AND_SET_SUPPORT) {
            item.setThrower(uuid);
        } else {
            if ((Object) item instanceof RefCraftItem && UUID_SUPPORT) {
                getHandle((RefCraftItem) (Object) item).throwerUUID = uuid;
            }
        }
    }
}
