package com.openosrs.client.core.bridge;

import com.openosrs.client.api.*;
import com.openosrs.client.core.ClientCore;
import com.openosrs.client.core.PlayerState;
import com.openosrs.client.core.InventoryState;
import com.openosrs.client.core.NetworkState;
import com.openosrs.client.core.InterfaceState;
import com.openosrs.client.core.WorldState;
import com.openosrs.client.api.types.GameObject;
import com.openosrs.client.api.types.GroundItem;
import com.openosrs.client.api.types.Item;
import com.openosrs.client.api.types.NPC;
import com.openosrs.client.api.types.Position;
import com.openosrs.client.api.types.Skill;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Bridge Adapter - Connects our API modules with the RuneLite bridge.
 *
 * This adapter class ensures that our API modules can access real game data
 * through the RuneLite bridge when available, while falling back to mock
 * data when the bridge is not active.
 */
public class BridgeAdapter {
    private static final Logger logger = LoggerFactory.getLogger(BridgeAdapter.class);

    private final ClientCore clientCore;
    private final RuneLiteBridge bridge;

    // State managers
    private final InventoryState inventoryState;
    private final PlayerState playerState;
    private final NetworkState networkState;
    private final InterfaceState interfaceState;
    private final WorldState worldState;

    public BridgeAdapter(ClientCore clientCore, RuneLiteBridge bridge) {
        this.clientCore = clientCore;
        this.bridge = bridge;

        // Initialize state managers
        this.inventoryState = clientCore.getInventoryState();
        this.playerState = clientCore.getPlayerState();
        this.networkState = clientCore.getNetworkState();
        this.interfaceState = clientCore.getInterfaceState();
        this.worldState = clientCore.getWorldState();

        logger.info("Bridge adapter initialized");
    }

    /**
     * Update all state from RuneLite bridge if available.
     */
    public void updateFromBridge() {
        if (!bridge.isActive()) {
            return;
        }

        try {
            updatePlayerState();
            updateInventoryState();
            updateWorldState();
            updateNetworkState();
        } catch (Exception e) {
            logger.warn("Error updating state from bridge: {}", e.getMessage(), e);
        }
    }

    /**
     * Update player state from bridge.
     */
    private void updatePlayerState() {
        if (playerState == null) {
            return;
        }

        // Update position
        Position position = bridge.getPlayerPosition();
        if (position != null) {
            playerState.setPosition(position);
        }

        // Update username
        String username = bridge.getUsername();
        if (username != null && !username.equals("Unknown")) {
            playerState.setUsername(username);
        }

        // Update run energy
        int runEnergy = bridge.getRunEnergy();
        playerState.setRunEnergy(runEnergy);

        // Update animation
        int animation = bridge.getCurrentAnimation();
        playerState.setCurrentAnimation(animation);

        // Update movement state
        boolean moving = bridge.isMoving();
        playerState.setMoving(moving);

        // Update skills
        for (Skill skill : Skill.values()) {
            int level = bridge.getSkillLevel(skill);
            int realLevel = bridge.getSkillRealLevel(skill);
            int experience = bridge.getSkillExperience(skill);

            playerState.setSkillLevel(skill, level);
            playerState.setSkillRealLevel(skill, realLevel);
            playerState.setSkillExperience(skill, experience);
        }
    }

    /**
     * Update inventory state from bridge.
     */
    private void updateInventoryState() {
        if (inventoryState == null) {
            return;
        }

        // Update inventory
        Item[] inventory = bridge.getInventory();
        if (inventory != null) {
            inventoryState.updateInventory(inventory);
        }

        // Update equipment
        Item[] equipment = bridge.getEquipment();
        if (equipment != null) {
            inventoryState.updateEquipment(equipment);
        }
    }

    /**
     * Update world state from bridge.
     */
    private void updateWorldState() {
        if (worldState == null) {
            return;
        }

        // Update NPCs
        List<NPC> npcs = bridge.getAllNPCs();
        if (npcs != null) {
            worldState.updateNPCs(npcs);
        }

        // Update game objects
        List<GameObject> objects = bridge.getAllGameObjects();
        if (objects != null) {
            worldState.updateGameObjects(objects);
        }

        // Update ground items
        List<GroundItem> groundItems = bridge.getAllGroundItems();
        if (groundItems != null) {
            worldState.updateGroundItems(groundItems);
        }

        // Update region if needed
        int gameState = bridge.getGameState();
        if (gameState == ClientCore.GameStateConstants.IN_GAME) {
            // In a real implementation, we'd get the current region from RuneLite
            // For now, we'll set a placeholder region ID
            // worldState.updateRegion(bridge.getCurrentRegion());
        }
    }

    /**
     * Update network state from bridge.
     */
    private void updateNetworkState() {
        if (networkState == null) {
            return;
        }

        // Update game state
        int gameState = bridge.getGameState();
        networkState.setGameState(gameState);

        // Update connection state based on game state
        boolean connected = gameState == ClientCore.GameStateConstants.IN_GAME ||
                           gameState == ClientCore.GameStateConstants.LOGGED_IN;
        networkState.setConnected(connected);
    }
    
    // === BRIDGED API METHODS ===

    /**
     * Get NPCs through bridge.
     */
    public List<NPC> getNPCs() {
        if (worldState != null) {
            return worldState.getAllNPCs();
        }
        return List.of(); // Empty list if world state not available
    }

    /**
     * Get game objects through bridge.
     */
    public List<GameObject> getGameObjects() {
        if (worldState != null) {
            return worldState.getAllGameObjects();
        }
        return List.of(); // Empty list if world state not available
    }

    /**
     * Get ground items through bridge.
     */
    public List<GroundItem> getGroundItems() {
        if (worldState != null) {
            return worldState.getAllGroundItems();
        }
        return List.of(); // Empty list if world state not available
    }

    /**
     * Get player position through bridge.
     */
    public Position getPlayerPosition() {
        if (playerState != null) {
            return playerState.getPosition();
        }
        return new Position(3200, 3200, 0); // Default position
    }

    /**
     * Get skill level through bridge.
     */
    public int getSkillLevel(Skill skill) {
        if (bridge.isActive()) {
            return bridge.getSkillLevel(skill);
        }
        return playerState != null ? playerState.getSkillLevel(skill) : 1;
    }

    /**
     * Get skill real level through bridge.
     */
    public int getSkillRealLevel(Skill skill) {
        if (bridge.isActive()) {
            return bridge.getSkillRealLevel(skill);
        }
        return playerState != null ? playerState.getSkillRealLevel(skill) : 1;
    }

    /**
     * Get skill experience through bridge.
     */
    public int getSkillExperience(Skill skill) {
        if (bridge.isActive()) {
            return bridge.getSkillExperience(skill);
        }
        return playerState != null ? playerState.getSkillExperience(skill) : 0;
    }

    /**
     * Get inventory through bridge.
     */
    public Item[] getInventory() {
        if (bridge.isActive()) {
            return bridge.getInventory();
        }
        return inventoryState != null ? inventoryState.getInventory() : new Item[28];
    }

    /**
     * Get equipment through bridge.
     */
    public Item[] getEquipment() {
        if (bridge.isActive()) {
            return bridge.getEquipment();
        }
        return inventoryState != null ? inventoryState.getEquipment() : new Item[14];
    }

    /**
     * Get run energy through bridge.
     */
    public int getRunEnergy() {
        if (bridge.isActive()) {
            return bridge.getRunEnergy();
        }
        return playerState != null ? playerState.getRunEnergy() : 100;
    }

    /**
     * Get current animation through bridge.
     */
    public int getCurrentAnimation() {
        if (bridge.isActive()) {
            return bridge.getCurrentAnimation();
        }
        return playerState != null ? playerState.getCurrentAnimation() : -1;
    }

    /**
     * Get username through bridge.
     */
    public String getUsername() {
        if (bridge.isActive()) {
            return bridge.getUsername();
        }
        return playerState != null ? playerState.getUsername() : "Unknown";
    }

    /**
     * Check if player is moving through bridge.
     */
    public boolean isMoving() {
        if (bridge.isActive()) {
            return bridge.isMoving();
        }
        return playerState != null ? playerState.isMoving() : false;
    }

    /**
     * Get game state through bridge.
     */
    public int getGameState() {
        if (bridge.isActive()) {
            return bridge.getGameState();
        }
        return networkState != null ? networkState.getGameState() : ClientCore.GameStateConstants.STARTUP;
    }
}