import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { loadPreferences } from '../config/preferences.js';
import { defaultTheme } from '../config/themes.js';
import { createTokenizer } from '../tokenization/index.js';
import { BoundedMap } from '../utils/bounded-map.js';
export function useAppState() {
    // Initialize theme and title shape from preferences
    const preferences = loadPreferences();
    const initialTheme = preferences.selectedTheme || defaultTheme;
    const initialTitleShape = preferences.titleShape || 'pill';
    const [client, setClient] = useState(null);
    const [messages, setMessages] = useState([]);
    const [displayMessages, setDisplayMessages] = useState([]);
    const [messageTokenCache, setMessageTokenCache] = useState(new BoundedMap({
        maxSize: 1000,
        // No TTL - cache is session-based and cleared on app restart
    }));
    const [currentModel, setCurrentModel] = useState('');
    const [currentProvider, setCurrentProvider] = useState('openai-compatible');
    const [currentTheme, setCurrentTheme] = useState(initialTheme);
    const [currentTitleShape, setCurrentTitleShape] = useState(initialTitleShape);
    const [toolManager, setToolManager] = useState(null);
    const [customCommandLoader, setCustomCommandLoader] = useState(null);
    const [customCommandExecutor, setCustomCommandExecutor] = useState(null);
    const [customCommandCache, setCustomCommandCache] = useState(new Map());
    const [startChat, setStartChat] = useState(false);
    const [mcpInitialized, setMcpInitialized] = useState(false);
    const [updateInfo, setUpdateInfo] = useState(null);
    // Connection status states
    const [mcpServersStatus, setMcpServersStatus] = useState([]);
    const [lspServersStatus, setLspServersStatus] = useState([]);
    // Initialization status states
    const [preferencesLoaded, setPreferencesLoaded] = useState(false);
    const [customCommandsCount, setCustomCommandsCount] = useState(0);
    // Cancelling indicator state
    const [isCancelling, setIsCancelling] = useState(false);
    const [isConversationComplete, setIsConversationComplete] = useState(false);
    // Cancellation state
    const [abortController, setAbortController] = useState(null);
    // Mode states
    const [isModelSelectionMode, setIsModelSelectionMode] = useState(false);
    const [isProviderSelectionMode, setIsProviderSelectionMode] = useState(false);
    const [isThemeSelectionMode, setIsThemeSelectionMode] = useState(false);
    const [isTitleShapeSelectionMode, setIsTitleShapeSelectionMode] = useState(false);
    const [isNanocoderShapeSelectionMode, setIsNanocoderShapeSelectionMode] = useState(false);
    const [isModelDatabaseMode, setIsModelDatabaseMode] = useState(false);
    const [isConfigWizardMode, setIsConfigWizardMode] = useState(false);
    const [isMcpWizardMode, setIsMcpWizardMode] = useState(false);
    const [isCheckpointLoadMode, setIsCheckpointLoadMode] = useState(false);
    const [checkpointLoadData, setCheckpointLoadData] = useState(null);
    const [isToolConfirmationMode, setIsToolConfirmationMode] = useState(false);
    const [isToolExecuting, setIsToolExecuting] = useState(false);
    // Development mode state
    const [developmentMode, setDevelopmentMode] = useState('normal');
    // Tool confirmation state
    const [pendingToolCalls, setPendingToolCalls] = useState([]);
    const [currentToolIndex, setCurrentToolIndex] = useState(0);
    const [completedToolResults, setCompletedToolResults] = useState([]);
    const [currentConversationContext, setCurrentConversationContext] = useState(null);
    // Chat queue for components
    const [chatComponents, setChatComponents] = useState([]);
    // Live component that renders outside Static for real-time updates (e.g., BashProgress)
    const [liveComponent, setLiveComponent] = useState(null);
    // Use ref for component key counter to avoid stale closure issues
    // State updates are async/batched, but ref updates are synchronous
    // This prevents duplicate keys when addToChatQueue is called rapidly
    const componentKeyCounterRef = useRef(0);
    // Get the next unique component key - synchronous to prevent duplicates
    const getNextComponentKey = useCallback(() => {
        componentKeyCounterRef.current += 1;
        return componentKeyCounterRef.current;
    }, []);
    // Helper function to add components to the chat queue with stable keys
    const addToChatQueue = useCallback((component) => {
        const newCounter = getNextComponentKey();
        let componentWithKey = component;
        if (React.isValidElement(component) && !component.key) {
            componentWithKey = React.cloneElement(component, {
                key: `chat-component-${newCounter}`,
            });
        }
        setChatComponents(prevComponents => [
            ...prevComponents,
            componentWithKey,
        ]);
    }, [getNextComponentKey]);
    // Create tokenizer based on current provider and model
    const tokenizer = useMemo(() => {
        if (currentProvider && currentModel) {
            return createTokenizer(currentProvider, currentModel);
        }
        // Fallback to simple char/4 heuristic if provider/model not set
        return createTokenizer('', '');
    }, [currentProvider, currentModel]);
    // Cleanup tokenizer resources when it changes
    useEffect(() => {
        return () => {
            if (tokenizer.free) {
                tokenizer.free();
            }
        };
    }, [tokenizer]);
    // Helper function for token calculation with caching
    const getMessageTokens = useCallback((message) => {
        const cacheKey = (message.content || '') + message.role + currentModel;
        const cachedTokens = messageTokenCache.get(cacheKey);
        if (cachedTokens !== undefined) {
            return cachedTokens;
        }
        const tokens = tokenizer.countTokens(message);
        // Defer cache update to avoid "Cannot update a component while rendering" error
        // This can happen when components call getMessageTokens during their render
        queueMicrotask(() => {
            setMessageTokenCache(prev => {
                const newCache = new BoundedMap({
                    maxSize: 1000,
                });
                // Copy existing entries
                for (const [k, v] of prev.entries()) {
                    newCache.set(k, v);
                }
                // Add new entry
                newCache.set(cacheKey, tokens);
                return newCache;
            });
        });
        return tokens;
    }, [messageTokenCache, tokenizer, currentModel]);
    // Message updater - no limits, display all messages
    const updateMessages = useCallback((newMessages) => {
        setMessages(newMessages);
        setDisplayMessages(newMessages);
    }, []);
    // Reset tool confirmation state
    const resetToolConfirmationState = () => {
        setIsToolConfirmationMode(false);
        setIsToolExecuting(false);
        setPendingToolCalls([]);
        setCurrentToolIndex(0);
        setCompletedToolResults([]);
        setCurrentConversationContext(null);
    };
    return {
        // State
        client,
        messages,
        displayMessages,
        messageTokenCache,
        currentModel,
        currentProvider,
        currentTheme,
        currentTitleShape,
        toolManager,
        customCommandLoader,
        customCommandExecutor,
        customCommandCache,
        startChat,
        mcpInitialized,
        updateInfo,
        mcpServersStatus,
        lspServersStatus,
        preferencesLoaded,
        customCommandsCount,
        isCancelling,
        isConversationComplete,
        abortController,
        isModelSelectionMode,
        isProviderSelectionMode,
        isThemeSelectionMode,
        isTitleShapeSelectionMode,
        isNanocoderShapeSelectionMode,
        isModelDatabaseMode,
        isConfigWizardMode,
        isMcpWizardMode,
        isCheckpointLoadMode,
        checkpointLoadData,
        isToolConfirmationMode,
        isToolExecuting,
        developmentMode,
        pendingToolCalls,
        currentToolIndex,
        completedToolResults,
        currentConversationContext,
        chatComponents,
        getNextComponentKey,
        tokenizer,
        // Setters
        setClient,
        setMessages,
        setDisplayMessages,
        setMessageTokenCache,
        setCurrentModel,
        setCurrentProvider,
        setCurrentTheme,
        setCurrentTitleShape,
        setToolManager,
        setCustomCommandLoader,
        setCustomCommandExecutor,
        setCustomCommandCache,
        setStartChat,
        setMcpInitialized,
        setUpdateInfo,
        setMcpServersStatus,
        setLspServersStatus,
        setPreferencesLoaded,
        setCustomCommandsCount,
        setIsCancelling,
        setIsConversationComplete,
        setAbortController,
        setIsModelSelectionMode,
        setIsProviderSelectionMode,
        setIsThemeSelectionMode,
        setIsTitleShapeSelectionMode,
        setIsNanocoderShapeSelectionMode,
        setIsModelDatabaseMode,
        setIsConfigWizardMode,
        setIsMcpWizardMode,
        setIsCheckpointLoadMode,
        setCheckpointLoadData,
        setIsToolConfirmationMode,
        setIsToolExecuting,
        setDevelopmentMode,
        setPendingToolCalls,
        setCurrentToolIndex,
        setCompletedToolResults,
        setCurrentConversationContext,
        setChatComponents,
        liveComponent,
        setLiveComponent,
        // Utilities
        addToChatQueue,
        getMessageTokens,
        updateMessages,
        resetToolConfirmationState,
    };
}
//# sourceMappingURL=useAppState.js.map