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


package engine.db.handlers;

import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.Mob;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class dbMobHandler extends dbHandlerBase {

    public dbMobHandler() {
        this.localClass = Mob.class;
        this.localObjectType = mbEnums.GameObjectType.valueOf(this.localClass.getSimpleName());
    }

    public Mob PERSIST(Mob toAdd) {

        Mob mobile = null;

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) {

            preparedStatement.setLong(1, toAdd.parentZoneUUID);
            preparedStatement.setInt(2, toAdd.loadID);
            preparedStatement.setInt(3, toAdd.guildUUID);
            preparedStatement.setFloat(4, toAdd.bindLoc.x);
            preparedStatement.setFloat(5, toAdd.bindLoc.y);
            preparedStatement.setFloat(6, toAdd.bindLoc.z);
            preparedStatement.setInt(7, 0);
            preparedStatement.setFloat(8, toAdd.spawnRadius);
            preparedStatement.setInt(9, toAdd.spawnDelay);
            preparedStatement.setInt(10, toAdd.contractUUID);
            preparedStatement.setInt(11, toAdd.buildingUUID);
            preparedStatement.setInt(12, toAdd.level);
            preparedStatement.setString(13, toAdd.firstName);
            preparedStatement.setString(14, toAdd.behaviourType.toString());

            ResultSet rs = preparedStatement.executeQuery();

            if (rs.next()) {
                int objectUUID = (int) rs.getLong("UID");

                if (objectUUID > 0)
                    mobile = GET_MOB(objectUUID);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return mobile;
    }

    public ArrayList<Mob> GET_ALL_MOBS() {

        ArrayList<Mob> mobileList = new ArrayList<>();

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_mob`.*, `object`.`parent` FROM `object` INNER JOIN `obj_mob` ON `obj_mob`.`UID` = `object`.`UID` ORDER BY `object`.`UID` ASC;")) {

            ResultSet rs = preparedStatement.executeQuery();
            mobileList = getObjectsFromRs(rs, 1000);

        } catch (SQLException e) {
            Logger.error(e);
        }

        return mobileList;
    }

    public boolean updateUpgradeTime(Mob mob, DateTime upgradeDateTime) {

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_mob SET upgradeDate=? "
                     + "WHERE UID = ?")) {

            if (upgradeDateTime == null)
                preparedStatement.setNull(1, java.sql.Types.DATE);
            else
                preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.getMillis()));

            preparedStatement.setInt(2, mob.getObjectUUID());

            preparedStatement.execute();
            return true;
        } catch (SQLException e) {
            Logger.error(e);
        }
        return false;
    }

    public int DELETE_MOB(final Mob mob) {

        int row_count = 0;
        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `object` WHERE `UID` = ?")) {

            preparedStatement.setLong(1, mob.getDBID());
            row_count = preparedStatement.executeUpdate();

        } catch (SQLException e) {
            Logger.error(e);

        }
        return row_count;
    }

    public void LOAD_GUARD_MINIONS(Mob guardCaptain) {

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `dyn_guards` WHERE `captainUID` = ?")) {

            preparedStatement.setInt(1, guardCaptain.getObjectUUID());
            ResultSet rs = preparedStatement.executeQuery();

            while (rs.next()) {
                String minionName = rs.getString("minionName");
                Mob toCreate = Mob.createGuardMinion(guardCaptain, guardCaptain.getLevel(), minionName);

                if (toCreate == null)
                    return;

                if (toCreate != null)
                    toCreate.setDeathTime(System.currentTimeMillis());

            }

        } catch (SQLException e) {
            Logger.error(e);
        }
    }

    public boolean ADD_GUARD_MINION(final long captainUID, final String minionName) {

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_guards` (`captainUID`, `minionName`) VALUES (?,?)")) {

            preparedStatement.setLong(1, captainUID);
            preparedStatement.setString(2, minionName);

            return (preparedStatement.executeUpdate() > 0);

        } catch (SQLException e) {
            Logger.error(e);
            return false;
        }
    }

    public boolean REMOVE_GUARD_MINION(final long captainUID, final String minionName) {

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=? AND `minionName`=? LIMIT 1;")) {

            preparedStatement.setLong(1, captainUID);
            preparedStatement.setString(2, minionName);

            return (preparedStatement.executeUpdate() > 0);

        } catch (SQLException e) {
            Logger.error(e);
            return false;
        }
    }

    public boolean REMOVE_ALL_MINIONS(final long captainUID) {

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=?;")) {

            preparedStatement.setLong(1, captainUID);

            return (preparedStatement.executeUpdate() > 0);

        } catch (SQLException e) {
            Logger.error(e);
            return false;
        }
    }

    public Mob GET_MOB(final int objectUUID) {

        Mob mobile = null;

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_mob`.*, `object`.`parent` FROM `object` INNER JOIN `obj_mob` ON `obj_mob`.`UID` = `object`.`UID` WHERE `object`.`UID` = ?;")) {

            preparedStatement.setLong(1, objectUUID);
            ResultSet rs = preparedStatement.executeQuery();
            mobile = (Mob) getObjectFromRs(rs);

        } catch (SQLException e) {
            Logger.error(e);
        }
        return mobile;
    }

    public int MOVE_MOB(long mobID, long parentID, float locX, float locY, float locZ) {

        int row_count = 0;

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `object` INNER JOIN `obj_mob` On `object`.`UID` = `obj_mob`.`UID` SET `object`.`parent`=?, `obj_mob`.`mob_spawnX`=?, `obj_mob`.`mob_spawnY`=?, `obj_mob`.`mob_spawnZ`=? WHERE `obj_mob`.`UID`=?;")) {

            preparedStatement.setLong(1, parentID);
            preparedStatement.setFloat(2, locX);
            preparedStatement.setFloat(3, locY);
            preparedStatement.setFloat(4, locZ);
            preparedStatement.setLong(5, mobID);

            ResultSet rs = preparedStatement.executeQuery();
            row_count = preparedStatement.executeUpdate();

        } catch (SQLException e) {
            Logger.error(e);
        }
        return row_count;
    }

    public String SET_PROPERTY(final Mob m, String name, Object new_value) {

        String result = "";

        try (Connection connection = DbManager.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement("CALL mob_SETPROP(?,?,?)")) {

            preparedStatement.setLong(1, m.getObjectUUID());
            preparedStatement.setString(2, name);
            preparedStatement.setString(3, String.valueOf(new_value));

            ResultSet rs = preparedStatement.executeQuery();

            if (rs.next())
                result = rs.getString("result");

        } catch (SQLException e) {
            Logger.error(e);
        }
        return result;
    }

}
