package data.scripts;

import java.text.NumberFormat;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;
import org.lwjgl.util.vector.Vector2f;

import com.fs.starfarer.api.GameState;
import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.ModSpecAPI;
import com.fs.starfarer.api.SettingsAPI;
import com.fs.starfarer.api.characters.PersonAPI;
import com.fs.starfarer.api.combat.AmmoTrackerAPI;
import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEngineLayers;
import com.fs.starfarer.api.combat.FluxTrackerAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ViewportAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
import com.fs.starfarer.api.graphics.SpriteAPI;
import com.fs.starfarer.api.impl.campaign.ids.Personalities;
import com.fs.starfarer.api.input.InputEventAPI;
import com.fs.starfarer.api.util.Misc;
import com.fs.starfarer.api.util.TimeoutTracker;
import com.fs.starfarer.combat.CombatViewport;
import com.fs.starfarer.combat.entities.Billboard;

import lunalib.lunaSettings.LunaSettings;

public class OIACCombatPlugin extends BaseEveryFrameCombatPlugin {
    public Billboard topic;
    private CombatEngineAPI engine = Global.getCombatEngine();
    private SpriteAPI image;
    private boolean hasInterest = false;
    private static final float SCREEN_WIDTH = Global.getSettings().getScreenWidth();
    private static final float SCREEN_HEIGHT = Global.getSettings().getScreenHeight();
    private TimeoutTracker<ShipAPI> tracker = new TimeoutTracker<ShipAPI>();
    private TimeoutTracker<Object> pressbutton = new TimeoutTracker<Object>();
    private TimeoutTracker<String> playerShipTracker = new TimeoutTracker<String>();
    private boolean playSound = false;
    private int volume = 50;
    private boolean ignorePlayerShip = true;
    private float voiceInterval = 8f;
    private int PressKeyCode = 16;
    private static final Object KEY = new Object();
    private String FriendlyvoicepackType = "";
    private String HostilevoicepackType = "";
    private boolean VPInit = false;

    public enum MODE {
        ALWAYS, NEVER, PRESSBUTTON;
    }

    private MODE mode;

    public void init(CombatEngineAPI engine) {
        topic = new Billboard(250f, 300f, "", "graphics/fonts/insignia21LTaa.fnt");
        image = Global.getSettings().getSprite("graphics/portraits/portrait_generic.png");
        playSound = LunaSettings.getBoolean("OIAC", "UseVoicePackage");
        volume = LunaSettings.getInt("OIAC", "VoicePackageVolume");
        ignorePlayerShip = LunaSettings.getBoolean("OIAC", "IgnorePlayerShip");
        voiceInterval = LunaSettings.getFloat("OIAC", "VoiceInterval");
        PressKeyCode = LunaSettings.getInt("OIAC", "InfoButton");
        String modesetting = LunaSettings.getString("OIAC", "InfoMode").trim();
        if (modesetting.equals("Always")) {
            mode = MODE.ALWAYS;
        } else if (modesetting.equals("Never")) {
            mode = MODE.NEVER;
        } else {
            mode = MODE.PRESSBUTTON;
        }
        /*
         * FriendlyvoicepackType = OIACI18nUtil.getString("OIACFriendlyVoicePackage",
         * LunaSettings.getString("OIAC", "FriendlyVoicePackageChoice").trim());
         * HostilevoicepackType = OIACI18nUtil.getString("OIACHostileVoicePackage",
         * LunaSettings.getString("OIAC", "HostileVoicePackageChoice").trim());
         */
        if (Global.getCurrentState() == GameState.TITLE) {
            return;
        } else {
            int FriendlyID = LunaSettings.getInt("OIAC", "FriendlyVoicePackage");
            int HostileID = LunaSettings.getInt("OIAC", "HostileVoicePackage");
            SettingsAPI settings = Global.getSettings();
            List<ModSpecAPI> mods = settings.getModManager().getEnabledModsCopy();
            String FriendlyVP = "NONE";
            String HostileVP = "NONE";
            int FriendlyLength = 0;
            int HostileLength = 0;
            for (ModSpecAPI mod : mods) {
                JSONArray csvData;
                try {
                    csvData = settings.loadCSV("data/voicepackage/OIACVoicePackages.csv", mod.getId());
                } catch (Exception e) {
                    continue;
                }
                for (int i = 0; i < csvData.length(); i++) {
                    try {
                        JSONObject row = csvData.getJSONObject(i);
                        String id = row.getString("VoicePackageID");
                        String type = row.getString("VoicePackageType");
                        if (!(id == null || type == null || id.equals("") || type.equals(""))) {
                            if (type.equals("Hostile")) {
                                //HostileVP = HostileVP + "," + id;
                                HostileLength++;
                                if (HostileLength == HostileID)
                                    HostileVP = id;
                            } else if (type.equals("Friendly")) {
                                //FriendlyVP = FriendlyVP + "," + id;
                                FriendlyLength++;
                                if (FriendlyLength == FriendlyID)
                                    FriendlyVP = id;
                                Global.getLogger(OIACCombatPlugin.class).info(FriendlyID+FriendlyVP);
                            }
                        }
                    } catch (Exception e) {
                    }
                }
            }
            FriendlyvoicepackType = OIACI18nUtil.getString("OIACFriendlyVoicePackage",
                    FriendlyVP);
            HostilevoicepackType = OIACI18nUtil.getString("OIACHostileVoicePackage",
                    HostileVP);
            VPInit = true;
        }
    }

    public void advance(float amount, List<InputEventAPI> events) {
        if (Global.getCurrentState() == GameState.TITLE)
            return;
        if(!VPInit){
            init(engine);
        }
        if (engine.getCombatUI() != null
                && (engine.getCombatUI().isShowingCommandUI() || engine.getCombatUI().isShowingDeploymentDialog()))
            return;
        // engine.maintainStatusForPlayerShip(KEY, null, LunaSettings.getString("OIAC",
        // "InfoMode"), LunaSettings.getString("OIAC", "InfoMode").trim(),
        // false);
        ViewportAPI viewport = engine.getViewport();
        if (viewport == null)
            return;
        tracker.advance(amount);
        pressbutton.advance(amount);
        Vector2f currMouseLocW = new Vector2f(viewport.convertScreenXToWorldX(Global.getSettings().getMouseX()),
                viewport.convertScreenYToWorldY(Global.getSettings().getMouseY()));
        ShipAPI interestShip = null;
        for (ShipAPI ship : engine.getShips()) {
            if (ship.isFighter() || !ship.isAlive() || (ignorePlayerShip && ship == engine.getPlayerShip()))
                continue;
            if (Misc.getDistance(ship.getLocation(), currMouseLocW) < ship.getCollisionRadius() * 0.9f) {
                interestShip = ship;
            }
        }
        if (mode == MODE.PRESSBUTTON) {
            for (InputEventAPI event : events) {
                if (event.isKeyboardEvent() && event.getEventValue() == PressKeyCode) {
                    if (pressbutton.contains(KEY)) {
                        pressbutton.set(KEY, 0.18f);
                    } else {
                        pressbutton.add(KEY, 0.4f);
                    }
                }
            }
        }
        boolean buttonPressed = pressbutton.contains(KEY);
        /*
         * if(playSound){
         * playSoundForPlayerShipIfNecessary(engine.getPlayerShip());
         * }
         */
        if (interestShip != null) {
            if (mode == MODE.ALWAYS
                    || buttonPressed) {
                hasInterest = true;
                updateBillboard(interestShip);
                // float radius = interestShip.getCollisionRadius();
                float radius = 220f;
                Vector2f topicloc = Vector2f.add(currMouseLocW,
                        new Vector2f(
                                (Global.getSettings().getMouseX() < SCREEN_WIDTH / 2 - 200f) ? radius : (-1 * radius),
                                (Global.getSettings().getMouseY() < SCREEN_HEIGHT / 2 - 150f) ? 0.5f * radius
                                        : (-0.5f * radius)),
                        null);
                topic.getLocation().set(topicloc);
            } else {
                hasInterest = false;
            }
            if (playSound) {
                playSoundIfNecessary(interestShip);
            }
        } else {
            hasInterest = false;
        }
    }

    public void renderInWorldCoords(ViewportAPI viewport) {
        if (hasInterest) {
            topic.render(CombatEngineLayers.ABOVE_SHIPS_AND_MISSILES_LAYER, (CombatViewport) viewport);
            
            Vector2f loc = topic.getLocation();
            Vector2f imageloc = Vector2f.add(loc, new Vector2f(157f, 113f), null);
            if (image != null)
                image.setSize(64f, 64f);
            image.renderAtCenter(imageloc.getX(), imageloc.getY());
        }
    }

    private void updateBillboard(ShipAPI ship) {
        String ShipName = ship.getName();
        String ShipHull = ship.getHullSpec().getHullName();
        String CaptainName = OIACI18nUtil.getMiscString("OIACNoCaptainName");
        String CaptainRank = "";
        if (ship.getCaptain() != null) {
            PersonAPI captain = ship.getCaptain();
            image = Global.getSettings().getSprite(captain.getPortraitSprite());
            if (ship.getCaptain().isAICore()) {
                CaptainName = captain.getAICoreId();
                CaptainRank = "AI";
            } else {
                CaptainName = captain.getNameString();
                CaptainRank = captain.getRank();
            }
        }
        String hpSection = "";
        if (LunaSettings.getBoolean("OIAC", "InfoHitpoints")) {
            float hpfrac = ship.getHitpoints() / ship.getMaxHitpoints() * 100;
            float hpLeft = ship.getHitpoints();
            hpSection = OIACI18nUtil.getMiscString("OIACHPFrac") + (int) hpfrac + "%" + "-" + (int) (hpLeft) + "\n";
        }
        String fluxSection = "";
        if (LunaSettings.getBoolean("OIAC", "InfoFlux")) {
            float fluxLevel = ship.getFluxLevel() * 100;
            float fluxLeft = ship.getMaxFlux() - ship.getCurrFlux();
            fluxSection = OIACI18nUtil.getMiscString("OIACFluxLevel") + (int) fluxLevel + "%" + "-" + (int) fluxLeft
                    + "\n";
        }
        String overloadOrVentSection = "";
        if (LunaSettings.getBoolean("OIAC", "InfoCriticalFlux")) {
            overloadOrVentSection = OIACI18nUtil.getMiscString("OIACNormalFlux");
            FluxTrackerAPI flux = ship.getFluxTracker();
            if (flux != null && flux.isOverloadedOrVenting()) {
                NumberFormat nf = NumberFormat.getNumberInstance();
                nf.setMaximumIntegerDigits(1);
                if (flux.isOverloaded()) {
                    float time = flux.getOverloadTimeRemaining();
                    overloadOrVentSection = OIACI18nUtil.getMiscString("OIACOverload") + "-"
                            + nf.format(time) + OIACI18nUtil.getMiscString("OIACUnitSec");
                } else {
                    float time = flux.getTimeToVent();
                    overloadOrVentSection = OIACI18nUtil.getMiscString("OIACVent") + "-"
                            + nf.format(time) + OIACI18nUtil.getMiscString("OIACUnitSec");
                }
            }
            overloadOrVentSection = overloadOrVentSection + "\n";
        }
        String DangerousWeaponSection = "";
        if (LunaSettings.getBoolean("OIAC", "InfoDangerousWeapon")) {
            WeaponSize largest = WeaponSize.SMALL;
            for (WeaponAPI weapon : ship.getAllWeapons()) {
                if (weapon.getSlot().isStationModule() || weapon.getSpec().getAIHints().contains(AIHints.PD)
                        || weapon.getSpec().getAIHints().contains(AIHints.PD_ONLY)) {

                } else {
                    largest = getLargerSize(largest, weapon.getSize());
                    if (weapon.getSize() == largest || weapon.getType() == WeaponType.MISSILE
                            || weapon.getType() == WeaponType.COMPOSITE || weapon.getType() == WeaponType.HYBRID
                            || weapon.getType() == WeaponType.SYNERGY || weapon.getType() == WeaponType.UNIVERSAL) {
                        NumberFormat nf = NumberFormat.getNumberInstance();
                        nf.setMaximumIntegerDigits(1);
                        if (weapon.isFiring() && weapon.getCooldownRemaining() <= 0) {
                            DangerousWeaponSection += (weapon.getDisplayName() + "-");
                            DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACDangerousWeaponFiring");
                            DangerousWeaponSection += "\n";
                        } else if (weapon.getCooldownRemaining() > 0) {
                            DangerousWeaponSection += (weapon.getDisplayName() + "-");
                            DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACDangerousWeaponCd");
                            DangerousWeaponSection += nf.format(weapon.getCooldownRemaining());
                            DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACUnitSec");
                            DangerousWeaponSection += "\n";
                        } else if (weapon.usesAmmo()) {
                            if (weapon.getAmmo() > 0) {
                                DangerousWeaponSection += (weapon.getDisplayName() + "-");
                                DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACDangerousWeaponAmmo");
                                DangerousWeaponSection += weapon.getAmmo();
                                DangerousWeaponSection += "\n";
                            } else if (weapon.getAmmoTracker().getReloadProgress() != 0) {
                                AmmoTrackerAPI Ammotracker = weapon.getAmmoTracker();
                                DangerousWeaponSection += (weapon.getDisplayName() + "-");
                                DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACDangerousWeaponAmmoReload");
                                DangerousWeaponSection += (Ammotracker.getReloadSize() / Ammotracker.getAmmoPerSecond()
                                        * (1 - Ammotracker.getReloadProgress()));
                                DangerousWeaponSection += OIACI18nUtil.getMiscString("OIACUnitSec");
                                DangerousWeaponSection += "\n";
                            }
                        }
                    }
                }
            }

        }
        if (CaptainName.isEmpty())
            CaptainName = OIACI18nUtil.getMiscString("OIACNoCaptainName");
        topic.setText(ShipName + "\n" + ShipHull + "\n" + CaptainRank + "-" + CaptainName + "\n"
                + hpSection
                + fluxSection + overloadOrVentSection + DangerousWeaponSection);
    }

    private static final String SMALL = "_Small";
    private static final String LARGE = "_Large";
    private static final String AGGRESSIVE = "_Aggressive";
    private static final String PHASE = "_Phase";
    private static final String STEADY = "_Steady";
    private static final String HAS_ORDER = "_Ordered";
    private static final String IDLE = "_Idle";
    private static final String ALLY = "_Ally";
    private static final String HOSTILE = "_Hostile";

    private void playSoundIfNecessary(ShipAPI ship) {
        if (!tracker.contains(ship)) {
            boolean isSmall = ship.isFrigate() || ship.isDestroyer();
            boolean isAggressive = ship.getCaptain().getPersonalityAPI().getId().equals(Personalities.AGGRESSIVE)
                    || ship.getCaptain().getPersonalityAPI().getId().equals(Personalities.RECKLESS);
            boolean isPhase = ship.getPhaseCloak() != null
                    && ship.getPhaseCloak().getSpecAPI().getId().equals("phasecloak");
            boolean hasOrder = ship.getShipTarget() != null;
            boolean isAlly = ship.getOwner() == engine.getPlayerShip().getOwner();

            String audioPicker = "";
            if (isAlly && !(FriendlyvoicepackType.equals("NONE")||FriendlyvoicepackType.equals(""))) {
                audioPicker = FriendlyvoicepackType;
                if (isSmall) {
                    audioPicker = audioPicker + SMALL;
                } else {
                    audioPicker = audioPicker + LARGE;
                }
                if (isPhase) {
                    audioPicker = audioPicker + PHASE;
                } else {
                    if (isAggressive) {
                        audioPicker = audioPicker + AGGRESSIVE;
                    } else {
                        audioPicker = audioPicker + STEADY;
                    }
                }
                if (hasOrder) {
                    audioPicker = audioPicker + HAS_ORDER;
                } else {
                    audioPicker = audioPicker + IDLE;
                }
                audioPicker = audioPicker + ALLY;
            } else if (!isAlly && !(HostilevoicepackType.equals("NONE")||HostilevoicepackType.equals(""))) {
                audioPicker = HostilevoicepackType;
                if (isSmall) {
                    audioPicker = audioPicker + SMALL;
                } else {
                    audioPicker = audioPicker + LARGE;
                }
                if (isPhase) {
                    audioPicker = audioPicker + PHASE;
                } else {
                    if (isAggressive) {
                        audioPicker = audioPicker + AGGRESSIVE;
                    } else {
                        audioPicker = audioPicker + STEADY;
                    }
                }
                if (hasOrder) {
                    audioPicker = audioPicker + HAS_ORDER;
                } else {
                    audioPicker = audioPicker + IDLE;
                }
                audioPicker = audioPicker + HOSTILE;
            }
            //Global.getSoundPlayer().playSound(audioPicker, 1f, volume / 100f,
            //        ship.getLocation(), ship.getVelocity());
            engine.maintainStatusForPlayerShip(ship, null, audioPicker, audioPicker,
            isAlly);
            // Global.getSoundPlayer().playSound("OIAC_StarCraft2_Small_Phase_Ordered_Ally",
            // 1f, volume / 100f,
            // ship.getLocation(), ship.getVelocity());
            tracker.add(ship, voiceInterval);
        }
    }

    private WeaponSize getLargerSize(WeaponSize o, WeaponSize n) {
        if (o == WeaponSize.SMALL && (n == WeaponSize.MEDIUM || n == WeaponSize.LARGE)) {
            return n;
        }
        if (o == WeaponSize.MEDIUM && n == WeaponSize.LARGE) {
            return n;
        }
        return o;
    }

}