<!-- 右侧插件栏 -->
<template>
  <div :class="{ 'not-selected': getMoveDragBarState() }">
    <div
      v-show="renderPanel && settingPluginsMeta[renderPanel]?.entry"
      id="tiny-engine-right-panel"
      :class="[renderPanel, { 'is-fixed': rightFixedPanelsStorage.includes(renderPanel) }]"
    >
      <div class="right-panel-wrap">
        <component
          :is="settingPluginsMeta[renderPanel]?.entry"
          :fixed-panels="rightFixedPanelsStorage"
          @close="close"
          @fixPanel="fixPanel"
        ></component>
        <div v-show="settingsState.activating" class="active2" />
      </div>
    </div>
  </div>
  <div id="tiny-engine-nav-panel">
    <vue-draggable-next
      id="rightTop"
      v-model="settingPlugins"
      filter=".panel-icon"
      class="nav-panel-lists"
      group="plugins"
      @end="onEnd"
    >
      <div
        v-for="(item, index) in settingPlugins"
        :key="index"
        :class="['list-item', { active: item === renderPanel }]"
        :title="settingPluginsMeta[item]?.title"
        @click="clickMenu({ item: settingPluginsMeta[item], index })"
        @contextmenu.prevent="showContextMenu($event, true, item, index, PLUGIN_POSITION.rightTop)"
      >
        <span class="item-icon" v-if="getPluginShown(item)">
          <svg-icon
            v-if="typeof settingPluginsMeta[item]?.icon === 'string'"
            :name="settingPluginsMeta[item]?.icon"
            class="panel-icon"
          ></svg-icon>
          <component v-else :is="settingPluginsMeta[item]?.icon" class="panel-icon"></component>
        </span>
      </div>
      <div style="flex: 1" class="list-item" @contextmenu.prevent="showContextMenu($event, false)"></div>
    </vue-draggable-next>
  </div>

  <plugin-right-menu
    ref="rightMenu"
    :list="Object.values(settingPluginsMeta)"
    :align="PLUGIN_POSITION.rightTop"
    @switchAlign="switchAlign"
  />
</template>

<script lang="ts">
/* metaService: engine.layout.DesignSettings */
import { computed, ref, watch } from 'vue'
import type { Component } from 'vue'
import { Tabs, TabItem } from '@opentiny/vue'
import { useLayout, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
import { VueDraggableNext } from 'vue-draggable-next'
import { PluginRightMenu } from '@opentiny/tiny-engine-common'

export default {
  components: {
    PluginRightMenu,
    TinyTabs: Tabs,
    TinyTabItem: TabItem,
    VueDraggableNext: VueDraggableNext as Component
  },
  props: {
    renderPanel: {
      type: String,
      default: ''
    },
    pluginList: {
      type: Array,
      default: () => []
    }
  },
  emits: ['changeRightAlign'],
  setup(props, { emit }) {
    const {
      getPluginById,
      PLUGIN_POSITION,
      rightFixedPanelsStorage,
      changeRightFixedPanels,
      dragPluginLayout,
      isSameSide,
      getPluginShown,
      getMoveDragBarState,
      layoutState: { settings: settingsState },
      getFinalLayoutConfig
    } = useLayout()

    const rightMenu = ref(null)
    const showContextMenu = (event, type, item, index, align) => {
      if (!type) {
        rightMenu.value.showContextMenu(event.clientX, event.clientY, type)
      } else {
        rightMenu.value.showContextMenu(event.clientX, event.clientY, type, item, index, align)
      }
    }

    const settingPlugins = ref(getFinalLayoutConfig().plugins.right.top)
    const settingPluginsMeta = computed(() => {
      const result: Record<string, any> = {}

      settingPlugins.value.forEach((item) => {
        const meta = getMergeMeta(item)
        if (meta) {
          result[item] = meta
        }
      })

      return result
    })

    const close = () => {
      useLayout().closeSetting(true)
    }

    const switchAlign = (index, id, from) => {
      settingPlugins.value.splice(index, 1)
      emit('changeRightAlign', id)
      if (!isSameSide(index, 0)) close()
      dragPluginLayout(from, PLUGIN_POSITION.leftTop, index, 0)
    }

    const changeAlign = (pluginId) => {
      const item = getPluginById(props.pluginList, pluginId)
      const existingItemIndex = settingPlugins.value.findIndex((plugin) => plugin.id === item.id)

      if (existingItemIndex !== -1) {
        settingPlugins.value.splice(existingItemIndex, 1)
      }
      settingPlugins.value.unshift(item)
    }

    const setRender = (curId) => {
      settingsState.render = curId
    }

    //点击右侧菜单icon按钮
    const clickMenu = ({ item }) => {
      if (settingsState.render == item.id) {
        useLayout().closeSetting(true)
        return
      }
      setRender(item.id)
    }

    watch(
      () => props.renderPanel,
      (n) => {
        setRender(n)
      }
    )

    //切换面板状态
    const fixPanel = (pluginName) => {
      changeRightFixedPanels(pluginName)
    }

    //监听拖拽结束事件
    const onEnd = (e) => {
      if (!isSameSide(e.from.id, e.to.id)) close()
      dragPluginLayout(e.from.id, e.to.id, e.oldIndex, e.newIndex)
    }

    return {
      changeAlign,
      settingsState,
      settingPlugins,
      clickMenu,
      close,
      fixPanel,
      rightFixedPanelsStorage,
      onEnd,
      showContextMenu,
      PLUGIN_POSITION,
      getPluginShown,
      switchAlign,
      rightMenu,
      getMoveDragBarState,
      getMergeMeta,
      settingPluginsMeta
    }
  }
}
</script>

<style lang="less" scoped>
#tiny-engine-right-panel {
  height: calc(100vh - var(--base-top-panel-height));
  border-left: 1px solid var(--te-layout-common-border-color);
  background: var(--te-layout-common-bg-color);
  display: flex;
  flex-direction: column;
  position: absolute;
  right: var(--base-nav-panel-width);
  z-index: 999;

  &.I18n {
    width: auto;
  }

  &.is-fixed {
    position: relative;
    top: 0;
    right: 0;
  }

  .right-panel-wrap {
    width: 100%;
    height: 100%;
    position: relative;
    :deep(.tiny-tabs__nav.is-show-active-bar) .tiny-tabs__item {
      margin-right: 0;
    }
  }
}

#tiny-engine-nav-panel {
  display: none;
  width: var(--base-nav-panel-width);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background: var(--te-layout-common-bg-color);
  box-sizing: border-box;
  z-index: 1000;
  border-left: 1px solid var(--te-layout-common-border-color);

  &.completed {
    display: block;
  }

  .nav-panel-lists {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;

    &.bottom {
      flex: 1;
      padding-bottom: 28px;
    }

    .list-item {
      width: 100%;
      padding: 3px 0;

      &:first-child {
        padding-top: 12px;
      }

      cursor: pointer;
      display: flex;
      justify-content: center;
      align-items: center;

      &:hover,
      &.active {
        .item-icon {
          background: var(--te-layout-common-bg-color-hover);
          border-radius: 4px;
        }
      }

      &.active {
        position: relative;

        .item-icon {
          color: var(--te-layout-common-text-color-secondary-checked);
        }
      }

      &.prev {
        border-bottom-color: var(--te-layout-common-border-color);
      }
    }

    .item-icon {
      display: flex;
      justify-content: center;
      align-items: center;
      color: var(--te-layout-common-text-color);
      font-size: 22px;
      width: 26px;
      height: 26px;

      svg {
        font-size: 18px;
      }
      .public-icon {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 26px;
        height: 26px;
      }
    }
  }
}

:deep(.panel-svg) {
  font-size: 18px;
}

:deep(.svg-icon.icon-plugin-icon-plugin-help) {
  font-size: 18px;
}

.not-selected {
  pointer-events: none;
  user-select: none;
}

:deep(.svg-icon.icon-plugin-icon-plugin-help) {
  font-size: 22px;
}

//高亮显示动画
.active2 {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  animation: glow 800ms ease-out infinite alternate;
  transition: opacity 1s linear;
}

@keyframes glow {
  0% {
    box-shadow: inset 0px 0px 4px var(--te-layout-panel-active-color);
  }
  100% {
    box-shadow: inset 0px 0px 14px var(--te-layout-panel-active-color);
  }
}
</style>