<template>
   <div class="column col-auto p-relative">
      <div ref="resizer" class="workspace-explorebar-resizer" />
      <div
         ref="explorebar"
         class="workspace-explorebar column"
         :style="{width: localWidth ? localWidth+'px' : ''}"
      >
         <div class="workspace-explorebar-header">
            <span class="workspace-explorebar-title">{{ connectionName }}</span>
            <span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools">
               <i
                  class="mdi mdi-18px mdi-database-plus c-hand mr-2"
                  :title="$t('message.createNewSchema')"
                  @click="showNewDBModal"
               />
               <i
                  class="mdi mdi-18px mdi-refresh c-hand mr-2"
                  :class="{'rotate':isRefreshing}"
                  :title="$t('word.refresh')"
                  @click="refresh"
               />
               <i
                  class="mdi mdi-18px mdi-power c-hand"
                  :title="$t('word.disconnect')"
                  @click="disconnectWorkspace(connection.uid)"
               />
            </span>
         </div>
         <div class="workspace-explorebar-search">
            <div v-if="workspace.connectionStatus === 'connected'" class="has-icon-right">
               <input
                  v-model="searchTerm"
                  class="form-input input-sm"
                  type="text"
                  :placeholder="$t('message.searchForElements')"
               >
               <i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px" />
               <i
                  v-else
                  class="form-icon c-hand mdi mdi-backspace mdi-18px pr-1"
                  @click="searchTerm = ''"
               />
            </div>
         </div>
         <div class="workspace-explorebar-body">
            <WorkspaceExploreBarSchema
               v-for="db of workspace.structure"
               :key="db.name"
               :database="db"
               :connection="connection"
               @show-schema-context="openSchemaContext"
               @show-table-context="openTableContext"
               @show-misc-context="openMiscContext"
               @show-misc-folder-context="openMiscFolderContext"
            />
         </div>
      </div>
      <ModalNewSchema
         v-if="isNewDBModal"
         @close="hideNewDBModal"
         @reload="refresh"
      />
      <ModalNewView
         v-if="isNewViewModal"
         :workspace="workspace"
         @close="hideCreateViewModal"
         @open-create-view-editor="openCreateViewEditor"
      />
      <ModalNewTrigger
         v-if="isNewTriggerModal"
         :workspace="workspace"
         @close="hideCreateTriggerModal"
         @open-create-trigger-editor="openCreateTriggerEditor"
      />
      <ModalNewRoutine
         v-if="isNewRoutineModal"
         :workspace="workspace"
         @close="hideCreateRoutineModal"
         @open-create-routine-editor="openCreateRoutineEditor"
      />
      <ModalNewFunction
         v-if="isNewFunctionModal"
         :workspace="workspace"
         @close="hideCreateFunctionModal"
         @open-create-function-editor="openCreateFunctionEditor"
      />
      <ModalNewTriggerFunction
         v-if="isNewTriggerFunctionModal"
         :workspace="workspace"
         @close="hideCreateTriggerFunctionModal"
         @open-create-function-editor="openCreateTriggerFunctionEditor"
      />
      <ModalNewScheduler
         v-if="isNewSchedulerModal"
         :workspace="workspace"
         @close="hideCreateSchedulerModal"
         @open-create-scheduler-editor="openCreateSchedulerEditor"
      />
      <DatabaseContext
         v-if="isDatabaseContext"
         :selected-schema="selectedSchema"
         :context-event="databaseContextEvent"
         @close-context="closeDatabaseContext"
         @open-create-table-tab="openCreateTableTab"
         @show-create-view-modal="showCreateViewModal"
         @show-create-trigger-modal="showCreateTriggerModal"
         @show-create-routine-modal="showCreateRoutineModal"
         @show-create-function-modal="showCreateFunctionModal"
         @show-create-trigger-function-modal="showCreateTriggerFunctionModal"
         @show-create-scheduler-modal="showCreateSchedulerModal"
         @reload="refresh"
      />
      <TableContext
         v-show="isTableContext"
         :selected-schema="selectedSchema"
         :selected-table="selectedTable"
         :context-event="tableContextEvent"
         @close-context="closeTableContext"
         @reload="refresh"
      />
      <MiscContext
         v-if="isMiscContext"
         :selected-misc="selectedMisc"
         :selected-schema="selectedSchema"
         :context-event="miscContextEvent"
         @close-context="closeMiscContext"
         @reload="refresh"
      />
      <MiscFolderContext
         v-if="isMiscFolderContext"
         :selected-misc="selectedMisc"
         :selected-schema="selectedSchema"
         :context-event="miscContextEvent"
         @show-create-trigger-modal="showCreateTriggerModal"
         @show-create-routine-modal="showCreateRoutineModal"
         @show-create-function-modal="showCreateFunctionModal"
         @show-create-trigger-function-modal="showCreateTriggerFunctionModal"
         @show-create-scheduler-modal="showCreateSchedulerModal"
         @close-context="closeMiscFolderContext"
         @reload="refresh"
      />
   </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';

import Tables from '@/ipc-api/Tables';
import Views from '@/ipc-api/Views';
import Triggers from '@/ipc-api/Triggers';
import Routines from '@/ipc-api/Routines';
import Functions from '@/ipc-api/Functions';
import Schedulers from '@/ipc-api/Schedulers';

import WorkspaceExploreBarSchema from '@/components/WorkspaceExploreBarSchema';
import DatabaseContext from '@/components/WorkspaceExploreBarSchemaContext';
import TableContext from '@/components/WorkspaceExploreBarTableContext';
import MiscContext from '@/components/WorkspaceExploreBarMiscContext';
import MiscFolderContext from '@/components/WorkspaceExploreBarMiscFolderContext';
import ModalNewSchema from '@/components/ModalNewSchema';
import ModalNewView from '@/components/ModalNewView';
import ModalNewTrigger from '@/components/ModalNewTrigger';
import ModalNewRoutine from '@/components/ModalNewRoutine';
import ModalNewFunction from '@/components/ModalNewFunction';
import ModalNewTriggerFunction from '@/components/ModalNewTriggerFunction';
import ModalNewScheduler from '@/components/ModalNewScheduler';

export default {
   name: 'WorkspaceExploreBar',
   components: {
      WorkspaceExploreBarSchema,
      DatabaseContext,
      TableContext,
      MiscContext,
      MiscFolderContext,
      ModalNewSchema,
      ModalNewView,
      ModalNewTrigger,
      ModalNewRoutine,
      ModalNewFunction,
      ModalNewTriggerFunction,
      ModalNewScheduler
   },
   props: {
      connection: Object,
      isSelected: Boolean
   },
   data () {
      return {
         isRefreshing: false,

         isNewDBModal: false,
         isNewViewModal: false,
         isNewTriggerModal: false,
         isNewRoutineModal: false,
         isNewFunctionModal: false,
         isNewTriggerFunctionModal: false,
         isNewSchedulerModal: false,

         localWidth: null,
         explorebarWidthInterval: null,
         searchTermInterval: null,
         isDatabaseContext: false,
         isTableContext: false,
         isMiscContext: false,
         isMiscFolderContext: false,

         databaseContextEvent: null,
         tableContextEvent: null,
         miscContextEvent: null,

         selectedSchema: '',
         selectedTable: null,
         selectedMisc: null,
         searchTerm: ''
      };
   },
   computed: {
      ...mapGetters({
         getWorkspace: 'workspaces/getWorkspace',
         explorebarSize: 'settings/getExplorebarSize',
         getConnectionName: 'connections/getConnectionName'
      }),
      workspace () {
         return this.getWorkspace(this.connection.uid);
      },
      connectionName () {
         return this.getConnectionName(this.connection.uid);
      },
      customizations () {
         return this.workspace.customizations;
      }
   },
   watch: {
      localWidth (val) {
         clearTimeout(this.explorebarWidthInterval);

         this.explorebarWidthInterval = setTimeout(() => {
            this.changeExplorebarSize(val);
         }, 500);
      },
      isSelected (val) {
         if (val) this.localWidth = this.explorebarSize;
      },
      searchTerm () {
         clearTimeout(this.searchTermInterval);

         this.searchTermInterval = setTimeout(() => {
            this.setSearchTerm(this.searchTerm);
         }, 200);
      }
   },
   created () {
      this.localWidth = this.explorebarSize;
   },
   mounted () {
      const resizer = this.$refs.resizer;

      resizer.addEventListener('mousedown', e => {
         e.preventDefault();

         window.addEventListener('mousemove', this.resize);
         window.addEventListener('mouseup', this.stopResize);
      });
   },
   methods: {
      ...mapActions({
         disconnectWorkspace: 'workspaces/removeConnected',
         refreshStructure: 'workspaces/refreshStructure',
         changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
         selectTab: 'workspaces/selectTab',
         newTab: 'workspaces/newTab',
         setSearchTerm: 'workspaces/setSearchTerm',
         addNotification: 'notifications/addNotification',
         changeExplorebarSize: 'settings/changeExplorebarSize'
      }),
      async refresh () {
         if (!this.isRefreshing) {
            this.isRefreshing = true;
            await this.refreshStructure(this.connection.uid);
            this.isRefreshing = false;
         }
      },
      resize (e) {
         const el = this.$refs.explorebar;
         let explorebarWidth = e.pageX - el.getBoundingClientRect().left;
         if (explorebarWidth > 500) explorebarWidth = 500;
         if (explorebarWidth < 150) explorebarWidth = 150;
         this.localWidth = explorebarWidth;
      },
      stopResize () {
         window.removeEventListener('mousemove', this.resize);
      },
      showNewDBModal () {
         this.isNewDBModal = true;
      },
      hideNewDBModal () {
         this.isNewDBModal = false;
      },
      openCreateTableTab () {
         this.closeDatabaseContext();

         this.newTab({
            uid: this.workspace.uid,
            schema: this.selectedSchema,
            elementName: '',
            elementType: 'table',
            type: 'new-table'
         });
      },
      hideCreateTableModal () {
         this.isNewTableModal = false;
      },
      async openCreateTableEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Tables.createTable(params);

         if (status === 'success') {
            await this.refresh();
            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'table',
               type: 'table-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      openSchemaContext (payload) {
         this.selectedSchema = payload.schema;
         this.databaseContextEvent = payload.event;
         this.isDatabaseContext = true;
      },
      closeDatabaseContext () {
         this.isDatabaseContext = false;
      },
      openTableContext (payload) {
         this.selectedTable = payload.table;
         this.selectedSchema = payload.schema;
         this.tableContextEvent = payload.event;
         this.isTableContext = true;
      },
      closeTableContext () {
         this.isTableContext = false;
      },
      openMiscContext (payload) {
         this.selectedMisc = payload.misc;
         this.selectedSchema = payload.schema;
         this.miscContextEvent = payload.event;
         this.isMiscContext = true;
      },
      openMiscFolderContext (payload) {
         this.selectedMisc = payload.type;
         this.selectedSchema = payload.schema;
         this.miscContextEvent = payload.event;
         this.isMiscFolderContext = true;
      },
      closeMiscContext () {
         this.isMiscContext = false;
      },
      closeMiscFolderContext () {
         this.isMiscFolderContext = false;
      },
      showCreateViewModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewViewModal = true;
      },
      hideCreateViewModal () {
         this.isNewViewModal = false;
      },
      async openCreateViewEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Views.createView(params);

         if (status === 'success') {
            await this.refresh();
            this.changeBreadcrumbs({ schema: this.selectedSchema, view: payload.name });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'view',
               type: 'view-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      showCreateTriggerModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewTriggerModal = true;
      },
      hideCreateTriggerModal () {
         this.isNewTriggerModal = false;
      },
      async openCreateTriggerEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Triggers.createTrigger(params);

         if (status === 'success') {
            await this.refresh();
            const triggerName = this.customizations.triggerTableInName ? `${payload.table}.${payload.name}` : payload.name;
            this.changeBreadcrumbs({ schema: this.selectedSchema, trigger: triggerName });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: triggerName,
               elementType: 'trigger',
               type: 'trigger-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      showCreateRoutineModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewRoutineModal = true;
      },
      hideCreateRoutineModal () {
         this.isNewRoutineModal = false;
      },
      async openCreateRoutineEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Routines.createRoutine(params);

         if (status === 'success') {
            await this.refresh();
            this.changeBreadcrumbs({ schema: this.selectedSchema, routine: payload.name });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'routine',
               type: 'routine-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      showCreateFunctionModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewFunctionModal = true;
      },
      hideCreateFunctionModal () {
         this.isNewFunctionModal = false;
      },
      showCreateTriggerFunctionModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewTriggerFunctionModal = true;
      },
      hideCreateTriggerFunctionModal () {
         this.isNewTriggerFunctionModal = false;
      },
      showCreateSchedulerModal () {
         this.closeDatabaseContext();
         this.closeMiscFolderContext();
         this.isNewSchedulerModal = true;
      },
      hideCreateSchedulerModal () {
         this.isNewSchedulerModal = false;
      },
      async openCreateFunctionEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Functions.createFunction(params);

         if (status === 'success') {
            await this.refresh();
            this.changeBreadcrumbs({ schema: this.selectedSchema, function: payload.name });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'function',
               type: 'function-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      async openCreateTriggerFunctionEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Functions.createTriggerFunction(params);

         if (status === 'success') {
            await this.refresh();
            this.changeBreadcrumbs({ schema: this.selectedSchema, triggerFunction: payload.name });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'triggerFunction',
               type: 'trigger-function-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      },
      async openCreateSchedulerEditor (payload) {
         const params = {
            uid: this.connection.uid,
            schema: this.selectedSchema,
            ...payload
         };

         const { status, response } = await Schedulers.createScheduler(params);

         if (status === 'success') {
            await this.refresh();
            this.changeBreadcrumbs({ schema: this.selectedSchema, scheduler: payload.name });

            this.newTab({
               uid: this.workspace.uid,
               schema: this.selectedSchema,
               elementName: payload.name,
               elementType: 'scheduler',
               type: 'scheduler-props'
            });
         }
         else
            this.addNotification({ status: 'error', message: response });
      }
   }
};
</script>

<style lang="scss">
  .workspace-explorebar-resizer {
    position: absolute;
    width: 4px;
    right: -2px;
    top: 0;
    height: calc(100vh - #{$excluding-size});
    cursor: ew-resize;
    z-index: 99;
    transition: background 0.2s;

    &:hover {
      background: rgba($primary-color, 50%);
    }
  }

  .workspace-explorebar {
    width: $explorebar-width;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: center;
    text-align: left;
    z-index: 8;
    flex: initial;
    position: relative;
    padding: 0;

    .workspace-explorebar-header {
      width: 100%;
      padding: 0.3rem;
      display: flex;
      justify-content: space-between;
      font-size: 0.6rem;
      font-weight: 700;
      text-transform: uppercase;

      .workspace-explorebar-title {
        width: 80%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
        align-items: center;
      }

      .workspace-explorebar-tools {
        display: flex;
        align-items: center;

        > i {
          opacity: 0.6;
          transition: opacity 0.2s;
          display: flex;
          align-items: center;

          &:hover {
            opacity: 1;
          }
        }
      }
    }

    .workspace-explorebar-search {
      width: 100%;
      display: flex;
      justify-content: space-between;
      font-size: 0.6rem;
      height: 28px;

      .has-icon-right {
        width: 100%;
        padding: 0.1rem;

        .form-icon {
          opacity: 0.5;
          transition: opacity 0.2s;
        }

        .form-input {
          height: 1.2rem;
          padding-left: 0.2rem;

          &:focus + .form-icon {
            opacity: 0.9;
          }

          &::placeholder {
            opacity: 0.6;
          }
        }
      }
    }

    .workspace-explorebar-body {
      width: 100%;
      height: calc((100vh - 58px) - #{$excluding-size});
      overflow: overlay;
      padding: 0 0.1rem;
    }
  }
</style>
