// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2022
//                www.magicbane.com


package engine.objects;

import engine.gameManager.DbManager;
import engine.gameManager.ItemManager;
import engine.gameManager.LootManager;
import engine.loot.BootySetEntry;
import engine.mbEnums;
import engine.server.MBServerStatics;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.concurrent.ConcurrentHashMap;

public class MobBase extends AbstractGameObject {

    private final int loadID;
    private final String firstName;
    private final byte level;
    private final float scale;
    public final ArrayList<MobBaseEffects> effectsList;
    public int bootySet;
    public mbEnums.MobBehaviourType fsm;
    public EnumSet<mbEnums.MonsterType> notEnemy;
    public EnumSet<mbEnums.MonsterType> enemy;
    private float healthMax;
    private int attackRating;
    private int defenseRating;
    private float damageMin;
    private float damageMax;
    private float hitBoxRadius;
    private EnumSet<mbEnums.MobFlagType> flags;
    private int mask;
    private int goldMod;
    private int seeInvis;
    private int spawnTime = 0;
    private float attackRange;
    private boolean isNecroPet = false;
    private MobBaseStats mobBaseStats;
    private float walk = 0;
    private float run = 0;
    private float walkCombat = 0;
    private float runCombat = 0;

    /**
     * ResultSet Constructor
     */
    public MobBase(ResultSet rs) throws SQLException {
        super(rs, rs.getInt("ID"));

        this.loadID = rs.getInt("loadID");

        this.firstName = rs.getString("name");
        this.level = rs.getByte("level");

        this.goldMod = rs.getInt("goldMod");
        this.spawnTime = rs.getInt("spawnTime");

        this.healthMax = rs.getInt("health");
        this.damageMin = rs.getFloat("minDmg");
        this.damageMax = rs.getFloat("maxDmg");

        this.attackRating = rs.getInt("atr");
        this.defenseRating = rs.getInt("defense");
        this.attackRange = rs.getFloat("attackRange");
        this.bootySet = rs.getInt("bootySet");

        this.fsm = mbEnums.MobBehaviourType.valueOf(rs.getString("fsm"));

        this.flags = mbEnums.fromLong(rs.getLong("flags"), mbEnums.MobFlagType.class);
        this.notEnemy = mbEnums.fromLong(rs.getLong("notEnemy"), mbEnums.MonsterType.class);
        this.enemy = mbEnums.fromLong(rs.getLong("enemy"), mbEnums.MonsterType.class);

        this.seeInvis = rs.getInt("seeInvis");
        this.scale = rs.getFloat("scale");
        this.hitBoxRadius = 5f;
        this.mask = 0;

        if (this.getObjectUUID() == 12021 || this.getObjectUUID() == 12022)
            this.isNecroPet = true;

        if (this.flags.contains(mbEnums.MobFlagType.HUMANOID))
            this.mask += MBServerStatics.MASK_HUMANOID;

        if (this.flags.contains(mbEnums.MobFlagType.UNDEAD))
            this.mask += MBServerStatics.MASK_UNDEAD;

        if (this.flags.contains(mbEnums.MobFlagType.BEAST))
            this.mask += MBServerStatics.MASK_BEAST;

        if (this.flags.contains(mbEnums.MobFlagType.DRAGON))
            this.mask += MBServerStatics.MASK_DRAGON;

        if (this.flags.contains(mbEnums.MobFlagType.RAT))
            this.mask += MBServerStatics.MASK_RAT;

        this.mobBaseStats = DbManager.MobBaseQueries.LOAD_STATS(this.loadID);
        DbManager.MobBaseQueries.LOAD_ALL_MOBBASE_SPEEDS(this);
        //load effects for mobbase
        this.effectsList = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.loadID);

    }

    public static ConcurrentHashMap<mbEnums.EquipSlotType, Item> loadEquipmentSet(int equipmentSetID) {

        ArrayList<BootySetEntry> equipList;
        ConcurrentHashMap<mbEnums.EquipSlotType, Item> equip = new ConcurrentHashMap<>();

        if (equipmentSetID == 0)
            return equip;

        equipList = LootManager._bootySetMap.get(equipmentSetID);

        if (equipList == null)
            return equip;

        for (BootySetEntry equipmentSetEntry : equipList) {

            Item item = new Item(equipmentSetEntry.templateID);
            item.objectUUID = ItemManager.lastNegativeID.decrementAndGet();
            item.drop_chance = equipmentSetEntry.dropChance;
            item.equipSlot = item.template.item_eq_slots_or.iterator().next();
            equip.put(item.equipSlot, item);

        }

        return equip;
    }

    public static MobBase getMobBase(int id) {
        return DbManager.MobBaseQueries.GET_MOBBASE(id);
    }

    public static int GetClassType(int mobbaseID) {

        switch (mobbaseID) {
            case 17235:
            case 17233:
            case 17256:
            case 17259:
            case 17260:
            case 17261:
                return 2518;
            case 17258:
            case 17257:
            case 17237:
            case 17234:
                return 2521;
            default:
                return 2518;
        }
    }

    public void updateSpeeds(float walk, float walkCombat, float run, float runCombat) {
        this.walk = walk;
        this.walkCombat = walkCombat;
        this.run = run;
        this.runCombat = runCombat;

    }

    /*
     * Getters
     */
    public String getFirstName() {
        return this.firstName;
    }

    public int getLoadID() {
        return this.loadID;
    }

    public int getLevel() {
        return this.level;
    }

    public float getHealthMax() {
        return this.healthMax;
    }

    public float getDamageMin() {
        return this.damageMin;
    }

    public float getDamageMax() {
        return this.damageMax;
    }

    public int getAttackRating() {
        return this.attackRating;
    }

    public int getDefenseRating() {
        return this.defenseRating;
    }

    public EnumSet<mbEnums.MobFlagType> getFlags() {
        return this.flags;
    }

    public float getScale() {
        return this.scale;
    }

    public int getTypeMasks() {
        return this.mask;
    }

    public int getSeeInvis() {
        return this.seeInvis;
    }

    public int getSpawnTime() {
        return this.spawnTime;
    }

    @Override
    public void updateDatabase() {
        // TODO Create update logic.
    }

    public float getHitBoxRadius() {
        if (this.hitBoxRadius < 0f) {
            return 0f;
        } else {
            return this.hitBoxRadius;
        }
    }

    public MobBaseStats getMobBaseStats() {
        return mobBaseStats;
    }

    public float getAttackRange() {
        return attackRange;
    }

    public boolean isNecroPet() {
        return isNecroPet;
    }

    public float getWalk() {
        return walk;
    }

    public void setWalk(float walk) {
        this.walk = walk;
    }

    public float getRun() {
        return run;
    }

    public void setRun(float run) {
        this.run = run;
    }

    public float getWalkCombat() {
        return walkCombat;
    }

    public float getRunCombat() {
        return runCombat;
    }

}
