<template>
  <AppShell :download-file="downloadFile" :download-folder="downloadFolder">
    <div v-if="!isConnected && messages.length === 0" class="app-loading-state">
      <div class="loading-animation" aria-hidden="true">
        <!-- From Uiverse.io by Nawsome -->
        <div class="boxes">
          <div class="box">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
          <div class="box">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
          <div class="box">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
          <div class="box">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
        </div>
      </div>
      <div class="loading-copy">
        <h2>加载中...</h2>
        <p>正在连接服务器，请稍候</p>
      </div>
    </div>

    <template v-else>
      <div class="main-container">
        <ConversationSidebar
          v-if="!isMobileViewport"
          :icon-style="iconStyle"
          :format-time="formatTime"
          :display-mode="chatDisplayMode"
          :display-mode-disabled="displayModeSwitchDisabled"
          @toggle="toggleSidebar"
          @create="createNewConversation"
          @search="handleSidebarSearch"
          @select="loadConversation"
          @load-more="loadMoreConversations"
          @personal="openPersonalPage"
          @delete="deleteConversation"
          @duplicate="duplicateConversation"
          @toggle-workspace="handleWorkspaceToggle"
          @toggle-display-mode="handleDisplayModeToggle"
        />

        <div v-if="!isMobileViewport" class="workspace-region">
          <LeftPanel
            ref="leftPanel"
            class="workspace-panel"
            :class="{ 'workspace-panel--collapsed': workspaceCollapsed }"
            :width="leftWidth"
            :collapsed="workspaceCollapsed"
            :icon-style="iconStyle"
            :agent-version="agentVersion"
            :thinking-mode="thinkingMode"
            :run-mode="resolvedRunMode"
            :is-connected="isConnected"
            :panel-menu-open="panelMenuOpen"
            :panel-mode="panelMode"
            :file-manager-disabled="policyUiBlocks.block_file_manager"
            @toggle-panel-menu="togglePanelMenu"
            @select-panel="selectPanelMode"
            @open-file-manager="openGuiFileManager"
            @toggle-thinking-mode="handleQuickModeToggle"
          />

          <div
            v-if="!workspaceCollapsed"
            class="resize-handle"
            @mousedown="startResize('left', $event)"
          ></div>
        </div>

        <main
          class="chat-container"
          :class="{
            'chat-container--immersive': workspaceCollapsed,
            'chat-container--mobile': isMobileViewport,
            'chat-container--monitor': chatDisplayMode === 'monitor',
            'has-title-ribbon': titleRibbonVisible
          }"
        >
          <TokenDrawer
            :visible="Boolean(currentConversationId)"
            :collapsed="tokenPanelCollapsed"
            @toggle="handleTokenPanelToggleClick"
            :current-conversation-tokens="currentConversationTokens"
            :current-context-tokens="currentContextTokens"
            :container-status="containerStatus"
            :container-net-rate="containerNetRate"
            :project-storage="projectStorage"
            :usage-quota="usageQuota"
            :format-token-count="formatTokenCount"
            :format-percentage="formatPercentage"
            :format-bytes="formatBytes"
            :format-quota-value="formatQuotaValue"
            :format-reset-time="formatResetTime"
            :format-rate="formatRate"
          />

          <div v-if="titleRibbonVisible" class="conversation-ribbon">
            <span class="conversation-ribbon__text">{{ titleTypingText || currentConversationTitle }}</span>
          </div>

          <ChatArea
            v-show="chatDisplayMode === 'chat'"
            ref="messagesArea"
            :messages="messages"
            :icon-style="iconStyle"
            :expanded-blocks="expandedBlocks"
            :render-markdown="renderMarkdown"
            :toggle-block="toggleBlock"
            :handle-thinking-scroll="handleThinkingScroll"
            :streaming-message="streamingMessage"
            :get-tool-icon="getToolIcon"
            :get-tool-status-text="getToolStatusText"
            :get-tool-animation-class="getToolAnimationClass"
            :get-tool-description="getToolDescription"
            :format-search-topic="formatSearchTopic"
            :format-search-time="formatSearchTime"
          />
          <VirtualMonitorSurface v-show="chatDisplayMode === 'monitor'" />

          <div v-if="blankHeroActive" class="blank-hero-overlay">
            <span class="icon icon-lg" :style="iconStyle('bot')" aria-hidden="true"></span>
            <p class="blank-hero-text">{{ blankWelcomeText }}</p>
          </div>

          <div
            v-if="chatDisplayMode === 'chat'"
            class="scroll-lock-toggle"
            :class="{ locked: autoScrollEnabled && !userScrolling && isOutputActive() }"
          >
            <button @click="toggleScrollLock" class="scroll-lock-btn">
              <svg
                v-if="autoScrollEnabled && !userScrolling && isOutputActive()"
                viewBox="0 0 24 24"
                aria-hidden="true"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <path d="M8 11h8a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1Z" />
                <path d="M9 11V8a3 3 0 0 1 6 0v3" />
              </svg>
              <svg v-else viewBox="0 0 24 24" aria-hidden="true" stroke-linecap="round" stroke-linejoin="round">
                <path d="M12 5v12" />
                <path d="M7 13l5 5 5-5" />
              </svg>
            </button>
          </div>

          <div class="composer-container" :class="{ 'blank-hero-mode': composerHeroActive }">
            <InputComposer
              ref="inputComposer"
              :input-message="inputMessage"
              :input-is-multiline="inputIsMultiline"
              :input-is-focused="inputIsFocused"
              :is-connected="isConnected"
              :streaming-message="composerBusy"
              :input-locked="displayLockEngaged"
              :uploading="uploading"
              :thinking-mode="thinkingMode"
              :run-mode="resolvedRunMode"
              :model-menu-open="modelMenuOpen"
              :model-options="modelOptions"
              :current-model-key="currentModelKey"
              :quick-menu-open="quickMenuOpen"
              :tool-menu-open="toolMenuOpen"
              :mode-menu-open="modeMenuOpen"
              :tool-settings="toolSettings"
              :tool-settings-loading="toolSettingsLoading"
              :settings-open="settingsOpen"
              :compressing="compressing"
              :current-conversation-id="currentConversationId"
              :icon-style="iconStyle"
              :tool-category-icon="toolCategoryIcon"
              :selected-images="selectedImages"
              :block-upload="policyUiBlocks.block_upload"
              :block-tool-toggle="policyUiBlocks.block_tool_toggle"
              :block-realtime-terminal="policyUiBlocks.block_realtime_terminal"
              :block-focus-panel="policyUiBlocks.block_focus_panel"
              :block-token-panel="policyUiBlocks.block_token_panel"
              :block-compress-conversation="policyUiBlocks.block_compress_conversation"
              :block-conversation-review="policyUiBlocks.block_conversation_review"
              @update:input-message="inputSetMessage"
              @input-change="handleInputChange"
              @input-focus="handleInputFocus"
              @input-blur="handleInputBlur"
              @toggle-quick-menu="toggleQuickMenu"
              @send-message="sendMessage"
              @send-or-stop="handleSendOrStop"
              @quick-upload="handleQuickUpload"
              @toggle-tool-menu="toggleToolMenu"
              @toggle-mode-menu="toggleModeMenu"
              @toggle-model-menu="toggleModelMenu"
              @select-run-mode="handleModeSelect"
              @select-model="handleModelSelect"
              @toggle-settings="toggleSettings"
              @update-tool-category="updateToolCategory"
              @realtime-terminal="handleRealtimeTerminalClick"
              @toggle-focus-panel="handleFocusPanelToggleClick"
              @toggle-token-panel="handleTokenPanelToggleClick"
              @compress-conversation="handleCompressConversationClick"
              @file-selected="handleFileSelected"
              @pick-images="openImagePicker"
              @remove-image="handleRemoveImage"
              @open-review="openReviewDialog"
            />
          </div>
        </main>

        <div v-if="!isMobileViewport" class="resize-handle" @mousedown="startResize('right', $event)"></div>

        <FocusPanel
          v-if="!isMobileViewport"
          :collapsed="rightCollapsed"
          :width="rightWidth"
          :icon-style="iconStyle"
          :get-language-class="getLanguageClass"
        />
      </div>

      <PersonalizationDrawer />
      <LiquidGlassWidget />
      <transition name="overlay-fade">
        <ImagePicker
          v-if="imagePickerOpen"
          :open="imagePickerOpen"
          :entries="imageEntries"
          :initial-selected="selectedImages"
          :loading="imageLoading"
          @close="closeImagePicker"
          @confirm="handleImagesConfirmed"
        />
      </transition>
      <transition name="overlay-fade">
        <ConversationReviewDialog
          v-if="reviewDialogOpen"
          :open="reviewDialogOpen"
          :conversations="conversations"
          :current-conversation-id="currentConversationId"
          :selected-id="reviewSelectedConversationId"
          :loading="conversationsLoading"
          :loading-more="loadingMoreConversations"
          :has-more="hasMoreConversations"
          :submitting="reviewSubmitting"
          :preview="reviewPreviewLines"
          :preview-loading="reviewPreviewLoading"
          :preview-error="reviewPreviewError"
          :preview-limit="reviewPreviewLimit"
          :send-to-model="reviewSendToModel"
          :generated-path="reviewGeneratedPath"
          @close="reviewDialogOpen = false"
          @select="handleReviewSelect"
          @load-more="loadMoreConversations"
          @toggle-send="reviewSendToModel = $event"
          @confirm="handleConfirmReview"
        />
      </transition>

      <div
        v-if="isMobileViewport"
        class="mobile-panel-trigger"
        :class="{ 'is-hidden': Boolean(activeMobileOverlay) }"
        ref="mobilePanelTrigger"
      >
        <div class="mobile-panel-topbar">
          <button type="button" class="mobile-panel-fab" aria-label="切换工作区" @click="toggleMobileOverlayMenu">
            <img :src="mobilePanelIcon" alt="" aria-hidden="true" />
          </button>
          <div class="mobile-topbar-title" :title="currentConversationTitle || '未命名对话'">
            {{ currentConversationTitle || '未命名对话' }}
          </div>
        </div>
        <transition name="mobile-panel-menu">
          <div v-if="mobileOverlayMenuOpen" class="mobile-panel-menu">
            <button
              type="button"
              class="mobile-menu-btn mobile-menu-btn--conversation"
              aria-label="对话记录"
              @click="openMobileOverlay('conversation')"
            >
              <svg class="mobile-menu-svg" viewBox="0 0 28 28" fill="none" aria-hidden="true">
                <path
                  d="M5 6.5c0-1.38 1.12-2.5 2.5-2.5h13c1.38 0 2.5 1.12 2.5 2.5v8.5c0 1.38-1.12 2.5-2.5 2.5h-5.6l-3.4 3.2.6-3.2H7.5c-1.38 0-2.5-1.12-2.5-2.5V6.5z"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="1.9"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                />
                <path d="M9 9.5h10" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" />
                <path d="M9 13h6" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" />
              </svg>
            </button>
            <button type="button" class="mobile-menu-btn" aria-label="工作台" @click="openMobileOverlay('workspace')">
              <img :src="mobileMenuIcons.workspace" alt="" aria-hidden="true" />
            </button>
            <button type="button" class="mobile-menu-btn" aria-label="聚焦面板" @click="openMobileOverlay('focus')">
              <img :src="mobileMenuIcons.focus" alt="" aria-hidden="true" />
            </button>
            <button type="button" class="mobile-menu-btn" aria-label="个人空间" @click="handleMobilePersonalClick">
              <img :src="mobileMenuIcons.personal" alt="" aria-hidden="true" />
            </button>
          </div>
        </transition>
      </div>

      <transition name="mobile-panel-overlay">
        <div
          v-if="isMobileViewport && activeMobileOverlay === 'conversation'"
          class="mobile-panel-overlay mobile-panel-overlay--left"
          @click.self="closeMobileOverlay"
        >
          <div class="mobile-panel-sheet mobile-panel-sheet--conversation">
            <ConversationSidebar
              class="mobile-overlay-content"
              :icon-style="iconStyle"
              :format-time="formatTime"
              :display-mode="chatDisplayMode"
              :display-mode-disabled="displayModeSwitchDisabled"
              :show-collapse-button="true"
              collapse-button-variant="close"
              @toggle="closeMobileOverlay"
              @create="createNewConversation"
              @search="handleSidebarSearch"
              @select="handleMobileOverlaySelect($event)"
              @load-more="loadMoreConversations"
              @personal="openPersonalPage"
              @delete="deleteConversation"
              @duplicate="duplicateConversation"
              @toggle-display-mode="handleDisplayModeToggle"
            />
          </div>
        </div>
      </transition>

      <transition name="mobile-panel-overlay">
        <div
          v-if="isMobileViewport && activeMobileOverlay === 'workspace'"
          class="mobile-panel-overlay mobile-panel-overlay--left"
          @click.self="closeMobileOverlay"
        >
          <div class="mobile-panel-sheet mobile-panel-sheet--workspace">
            <button type="button" class="mobile-overlay-close" aria-label="关闭面板" @click="closeMobileOverlay">
              ×
            </button>
            <LeftPanel
              class="mobile-overlay-content"
              :width="Math.min(leftWidth, 420)"
              :icon-style="iconStyle"
              :agent-version="agentVersion"
              :thinking-mode="thinkingMode"
              :is-connected="isConnected"
              :panel-menu-open="panelMenuOpen"
              :panel-mode="panelMode"
              @toggle-panel-menu="togglePanelMenu"
              @select-panel="selectPanelMode"
              @open-file-manager="openGuiFileManager"
            />
          </div>
        </div>
      </transition>

      <transition name="mobile-panel-overlay">
        <div
          v-if="isMobileViewport && activeMobileOverlay === 'focus'"
          class="mobile-panel-overlay mobile-panel-overlay--right"
          @click.self="closeMobileOverlay"
        >
          <div class="mobile-panel-sheet mobile-panel-sheet--focus">
            <FocusPanel
              class="mobile-overlay-content"
              :collapsed="false"
              :width="Math.min(rightWidth, 420)"
              :icon-style="iconStyle"
              :get-language-class="getLanguageClass"
              :show-close-button="true"
              @close="closeMobileOverlay"
            />
          </div>
        </div>
      </transition>
    </template>
  </AppShell>
</template>

<script setup lang="ts">
import appOptions from './app';
import VirtualMonitorSurface from './components/chat/VirtualMonitorSurface.vue';

const mobilePanelIcon = new URL('../icons/align-left.svg', import.meta.url).href;
const mobileMenuIcons = {
  workspace: new URL('../icons/folder.svg', import.meta.url).href,
  focus: new URL('../icons/eye.svg', import.meta.url).href,
  personal: new URL('../icons/user.svg', import.meta.url).href
};

defineOptions(appOptions);
</script>
