{% raw %}
<div id="app">
  <div ref="menu" class="menu scrollable-menu" v-bind:class="{ 'active': menuVisible }">
    <div ref="menuCloseButton" class="close"><i class="fas fa-window-close"></i></div>
    <div class="mode-selector">
        <label>Mode:</label>
        <div class="mode-buttons">
            <button 
                @click="mode = 'opensesame'" 
                :class="{ active: mode === 'opensesame' }">
                <img src="/static/opensesame.png" alt="OpenSesame Icon">
                <span>OpenSesame expert</span>
            </button>
            <button 
                @click="mode = 'academic'" 
                :class="{ active: mode === 'academic' }">
                <img src="/static/sigmund-avatar.png" alt="Academic Icon">
                <span>Research assistant</span>
            </button>
        </div>
    </div>    
    <div class="tools-section" v-show="mode === 'academic'">
        <label>Tools:</label>
        <div class="tool-item">
            <input type="checkbox" 
                   id="tool-search-google-scholar" 
                   v-model="tool_search_google_scholar">
            <label for="tool-search-google-scholar">Google Scholar</label>
        </div>
        <div class="tool-item">
            <input type="checkbox" 
                   id="tool-execute-code" 
                   v-model="tool_execute_code">
            <label for="tool-execute-code">Code execution</label>
        </div>
        <div class="tool-item">
            <input type="checkbox" 
                   id="tool-generate-image" 
                   v-model="tool_generate_image">
            <label for="tool-generate-image">Image generation</label>
        </div>
        <div class="tool-item">
            <input type="checkbox" 
                   id="tool-download" 
                   v-model="tool_download">
            <label for="tool-download">Download</label>
        </div>            
        <div class="tool-item">
            <input type="checkbox" 
                   id="tool-read-attachment" 
                   v-model="tool_read_attachment">
            <label for="tool-read-attachment">Attachments</label>
        </div>
        <small>Only enable tools that you need for best performance</small>
    </div>
    <hr class="menu-divider">
    <!-- Model selection -->
    <div class="model-selector">
        <label>AI model:</label>
        <div class="model-buttons">
            <button 
                @click="modelConfig = 'openai'" 
                :class="{ active: modelConfig === 'openai' }">
                <!-- Icon for OpenAI model -->
                <img src="/static/openai.png" alt="OpenAI Icon">
                <span>OpenAI<br><small>GPT4o<br/>Conversations</small></span>
            </button>
            <button 
                @click="modelConfig = 'openai_o1'" 
                :class="{ active: modelConfig === 'openai_o1' }">
                <!-- Icon for OpenAI model -->
                <img src="/static/openai.png" alt="OpenAI Icon">
                <span>OpenAI<br><small>o1<br/>Problem solving</small></span>
            </button>
            <button 
                @click="modelConfig = 'anthropic'" 
                :class="{ active: modelConfig === 'anthropic' }">
                <!-- Icon for Anthropic model -->
                <img src="/static/anthropic.png" alt="Anthropic Icon">
                <span>Anthropic<br><small>Claude 3.5</small></span>
            </button>
            <button 
                @click="modelConfig = 'mistral'" 
                :class="{ active: modelConfig === 'mistral' }">
                <!-- Icon for Mistral model -->
                <img src="/static/mistral.png" alt="Mistral Icon">
                <span>Mistral<br><small>Large</small></span>
            </button>
        </div>
        <small>For OpenSesame, o1 is  most effective. For other tasks, each model has its own strengths.</small>
    </div>    
    <hr class="menu-divider">
    <div v-if="shouldShowNewConversationButton" @click="navigateTo(getNewConversationUrl())">New conversation</div>
    <div @click="showConversations">Browse conversations</div>
    <div @click="navigateTo('/api/conversation/clear')">Clear conversation</div>
    <div @click="showAttachments">Browse attachments</div>
    <hr class="menu-divider">    
    <div @click="navigateTo('/about')">About</div>
    <div @click="navigateTo('/terms')">Terms and conditions</div>
    <div @click="navigateTo('/subscribe/customer-portal')" v-if="showManageSubscriptions">Manage subscription</div>
    <div @click="navigateTo('/logout')">Log out</div>
  </div>
  <!-- Modal for browsing conversations -->
  <div class="modal" v-if="showModal" v-bind:class="{ 'active': showModal }">
    <div class="modal-content">
      <div id='conversation-heading'>Conversations
        <div class="close" @click="closeModal"><i class="fas fa-window-close"></i></div>
      </div>
      <!-- Search input and button -->
      <div class="search-conversations">
          <input v-model="searchQuery" @keydown.enter="fetchConversations" type="text" placeholder="Search …">
      </div>      
      <div id="loadingConversationsMessage" v-show="isLoadingConversations">Loading conversations …</div>
      <div v-for="(conversation, index) in sortedConversations" :key="conversation.id">
        <span v-if="index !== 0" class="delete-convo" @click="deleteConversation(conversation.id)">
          <i class="fas fa-trash-alt"></i>
        </span>
        <span @click="activateConversation(conversation.id)" class="conversation-title">
          {{ conversation.title }}
        </span>
      </div>
    </div>
  </div>
  <!-- Modal for browsing attachments -->
  <div class="modal" v-if="showAttachmentsModal" v-bind:class="{ 'active': showAttachmentsModal }">
    <div class="modal-content">
      <div id='attachment-heading'>Attachments
        <div class="close" @click="closeAttachmentsModal"><i class="fas fa-window-close"></i></div>
      </div>
      <div id="loadingAttachmentsMessage" v-show="isLoadingAttachments">Loading attachments …</div>
      <div v-if="Object.keys(attachments).length === 0" class="no-attachments">
        No attachments
      </div>
      <div v-else v-for="(attachment, id) in attachments" :key="id">
        <span class="delete-attachment" @click="deleteAttachment(id)">
          <i class="fas fa-trash-alt"></i>
        </span>
        <span class="attachment-filename" @click="downloadAttachment(id)">
          {{ attachment.filename }}
        </span>
        <span class="attachment-description" @click="downloadAttachment(id)">
          {{ attachment.description }}
        </span>
      </div>
      <!-- Upload section -->
      <div class="attachment-upload">
        <div id="uploadMessage" v-show="isUploading">Uploading and reading, please wait …</div>
        <div class="file-upload-wrapper">
          <button class="file-upload-button">
            <i class="fas fa-cloud-upload-alt"></i> Upload File
          </button>
          <input type="file" class="file-upload-input" id="fileInput" @change="uploadAttachment" />
        </div>
      </div>
    </div>
  </div>
</div>
{% endraw %}

<script>
function setSetting(key, value) {
  const data = {};
  data[key] = String(value);
  console.log('setting:', key, ' = ', data);
  fetch('/api/setting/set', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(data),
  })
  .then((response) => {
    if (!response.ok) {
      throw new Error(`Failed to set ${key} setting: ${response.statusText}`);
    }
    return response.json();
  })
  .then((json) => {
    if (!json.success) {
      throw new Error(`Failed to set ${key} setting: ${json.message}`);
    }
  })
  .catch((error) => {
    console.error(error);
  });
}

new Vue({
  el: '#app',
  data: {
    menuVisible: false,
    showModal: false,
    conversations: {},
    showAttachmentsModal: false,
    showManageSubscriptions: {{ subscription_required|lower }},
    attachments: {},
    isUploading: false,
    modelConfig: sigmundSettings.model_config,
    forceModelConfigUpdate: 0,
    mode: sigmundSettings.mode,
    tool_download: sigmundSettings.tool_download === 'true',
    tool_execute_code: sigmundSettings.tool_execute_code === 'true',
    tool_generate_image: sigmundSettings.tool_generate_image === 'true',
    tool_read_attachment: sigmundSettings.tool_read_attachment === 'true',
    tool_search_google_scholar: sigmundSettings.tool_search_google_scholar === 'true',
    shouldShowNewConversationButton: true,
    isLoadingConversations: true,
    isLoadingAttachments: true,
    searchQuery: ''
  },
  computed: {
    sortedConversations() {
      return Object.entries(this.conversations)
        .map(([id, [title, timestamp]]) => ({ id, title, timestamp }))
        .sort((a, b) => b.timestamp - a.timestamp);
    }
  },
  watch: {
    modelConfig(value) { setSetting('model_config', value); },
    mode(value) { setSetting('mode', value); },
    tool_download(value) { setSetting('tool_download', value); },
    tool_execute_code(value) { setSetting('tool_execute_code', value); },
    tool_generate_image(value) { setSetting('tool_generate_image', value); },
    tool_read_attachment(value) { setSetting('tool_read_attachment', value); },
    tool_search_google_scholar(value) { setSetting('tool_search_google_scholar', value); }
  },
  methods: {
    closeMenu(event) {
      // Only close the menu if the click was not inside the menu
      if (this.$refs.menuCloseButton.contains(event.target) || !this.$refs.menu.contains(event.target)) {
        this.menuVisible = false;
        window.removeEventListener('click', this.closeMenu);
      }
    },
    getNewConversationUrl() {
      return '/api/conversation/new';
    },
    toggleMenu: function() {
      const responseElement = document.getElementById('response');
      this.shouldShowNewConversationButton = responseElement.children.length > 1;
      this.menuVisible = !this.menuVisible;
      // Attach an event handler to close the menu when the window is clicked.
      // This is done in a timeout to avoid it from being invoked directly as
      // a result of the current click
      setTimeout(() => {
        if (this.menuVisible) {
          window.addEventListener('click', this.closeMenu);
        }
      }, 100);
    },
    navigateTo: function(path) {
      window.location.href = path;
    },
    showConversations: function() {
      this.fetchConversations();
      this.showModal = true;
      this.menuVisible = false;
      console.log('showing conversations')
    },
    closeModal: function() {
      this.showModal = false;
    },
    fetchConversations(query = '') {
        this.conversations = {};
        this.isLoadingConversations = true;
        fetch(`/api/conversation/list?query=${encodeURIComponent(this.searchQuery)}`)
            .then(response => response.json())
            .then(data => {
                console.log(data);
                this.conversations = data;
                this.isLoadingConversations = false;
            })
            .catch(error => {
                console.error('Error fetching conversations:', error);
            });
    },
    activateConversation: function(conversationId) {
      this.navigateTo(`/api/conversation/activate/${conversationId}`);
    },
    deleteConversation: function(conversationId) {
      // Optimistically remove the conversation from the list
      Vue.delete(this.conversations, conversationId);
      // Make delete request to server
      fetch(`/api/conversation/delete/${conversationId}`, { method: 'DELETE' })
        .then(response => {
          if (!response.ok) {
            // If the delete failed, add it back to the list
            this.fetchConversations();
          }
        });
    },
    showAttachments: function() {
      this.fetchAttachments();
      this.showAttachmentsModal = true;
      this.menuVisible = false;
      console.log('showing attachments');
    },
    closeAttachmentsModal: function() {
      this.showAttachmentsModal = false;
    },
    fetchAttachments: function() {
      fetch('/api/attachments/list')
        .then(response => response.json())
        .then(data => {
          this.attachments = data;
          this.isLoadingAttachments = false;
        })
        .catch(error => {
          console.error('Error fetching attachments:', error);
        });
    },
    downloadAttachment: function(attachmentId) {
      window.location.href = `/api/attachments/get/${attachmentId}`;
    },
    deleteAttachment: function(attachmentId) {
      // Optimistically remove the attachment from the list
      Vue.delete(this.attachments, attachmentId);
      // Make delete request to server
      fetch(`/api/attachments/delete/${attachmentId}`, { method: 'DELETE' })
        .then(response => {
          if (!response.ok) {
            // If the delete failed, add it back to the list
            this.fetchAttachments();
          }
        });
    },
    uploadAttachment: function(event) {
      this.isUploading = true;
      const fileInput = event.target;
      if (fileInput.files.length === 0) {
        return;
      }
      const file = fileInput.files[0];
      const formData = new FormData();
      formData.append('file', file);

      const xhr = new XMLHttpRequest();
      xhr.open('POST', '/api/attachments/add', true);
      xhr.onload = () => {
        if (xhr.status === 200) {
          const response = JSON.parse(xhr.responseText);
          if (response.success) {
            this.fetchAttachments(); // Refresh the list after upload
          } else {
            // Handle error
            console.error('Upload failed:', response.message);
          }
        } else {
          // Handle error
          console.error('Error during upload:', xhr.statusText);
        }
        this.isUploading = false;
      };

      xhr.send(formData);
    }
  }
});
</script>
