package com.openosrs.client.scripting;

import com.openosrs.client.api.AgentAPI;
import com.openosrs.client.core.ClientCore;
import com.openosrs.client.core.EventSystem;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Enhanced script execution context with additional capabilities.
 */
public class ScriptContext {
    private final String executionId;
    private final AgentAPI api;
    private final ClientCore clientCore;
    private final EventSystem eventSystem;
    private final ScriptConfiguration configuration;
    private final long startTime;
    private final Map<String, Object> variables;
    private volatile ScriptStatus status;
    private volatile boolean shouldStop;
    private volatile String error;
    private volatile long lastActivityTime;
    
    public ScriptContext(String executionId, AgentAPI api, ClientCore clientCore, EventSystem eventSystem, ScriptConfiguration configuration) {
        this.executionId = executionId;
        this.api = api;
        this.clientCore = clientCore;
        this.eventSystem = eventSystem;
        this.configuration = configuration;
        this.startTime = System.currentTimeMillis();
        this.status = ScriptStatus.PENDING;
        this.shouldStop = false;
        this.variables = new ConcurrentHashMap<>();
        this.lastActivityTime = System.currentTimeMillis();
    }
    
    public String getExecutionId() { return executionId; }
    public AgentAPI getAPI() { return api; }
    public ClientCore getClientCore() { return clientCore; }
    public EventSystem getEventSystem() { return eventSystem; }
    public ScriptConfiguration getConfiguration() { return configuration; }
    public long getStartTime() { return startTime; }
    
    public ScriptStatus getStatus() { return status; }
    public void setStatus(ScriptStatus status) { 
        this.status = status;
        updateActivity();
    }
    
    public boolean shouldStop() { return shouldStop; }
    public void stop() { 
        this.shouldStop = true;
        updateActivity();
    }
    
    public String getError() { return error; }
    public void setError(String error) { 
        this.error = error;
        updateActivity();
    }
    
    public long getLastActivityTime() { return lastActivityTime; }
    private void updateActivity() { this.lastActivityTime = System.currentTimeMillis(); }
    
    /**
     * Store a variable in the script context.
     */
    public void setVariable(String key, Object value) {
        variables.put(key, value);
        updateActivity();
    }
    
    /**
     * Retrieve a variable from the script context.
     */
    @SuppressWarnings("unchecked")
    public <T> T getVariable(String key, Class<T> type) {
        Object value = variables.get(key);
        return type.isInstance(value) ? (T) value : null;
    }
    
    /**
     * Check if script should continue running.
     */
    public void checkContinue() throws InterruptedException {
        updateActivity();
        if (shouldStop || Thread.currentThread().isInterrupted()) {
            throw new InterruptedException("Script execution interrupted");
        }
    }
    
    /**
     * Log a message with script context.
     */
    public void log(String level, String message, Object... args) {
        updateActivity();
        String formattedMessage = String.format("[%s] %s", executionId, String.format(message, args));
        
        switch (level.toLowerCase()) {
            case "debug":
                LoggerFactory.getLogger("ScriptLogger").debug(formattedMessage);
                break;
            case "info":
                LoggerFactory.getLogger("ScriptLogger").info(formattedMessage);
                break;
            case "warn":
                LoggerFactory.getLogger("ScriptLogger").warn(formattedMessage);
                break;
            case "error":
                LoggerFactory.getLogger("ScriptLogger").error(formattedMessage);
                break;
            default:
                LoggerFactory.getLogger("ScriptLogger").info(formattedMessage);
        }
    }
}