<template>
  <div class="position-group">
    <div
      :class="['position-label', { 'is-setting': getSettingFlag(POSITION_PROPERTY.Position) }]"
      title="position"
      @click="openSetting(POSITION_PROPERTY.Position, $event)"
    >
      <span>定位</span>
    </div>
    <div class="position-select">
      <select-configurator
        :modelValue="state.selectValue"
        :options="selectOptions"
        @update:modelValue="selectPosition"
      ></select-configurator>
    </div>
    <div v-if="state.showSetting" class="position-dropdown">
      <div v-if="state.showSettingIcon" class="tooltip-wrap">
        <div class="tooltip-icon">
          <tiny-tooltip
            v-for="(item, index) in positionOptions"
            :key="index"
            effect="light"
            placement="top"
            :open-delay="500"
            :content="item.tip"
          >
            <span
              :class="['icon-wrap', { selected: index === state.selectedIndex }]"
              @click="selectInsetValue(item, index)"
              ><svg-icon :name="item.icon"></svg-icon
            ></span>
          </tiny-tooltip>
        </div>
      </div>
      <div class="setting-wrap">
        <div class="setting">
          <svg xmlns="http://www.w3.org/2000/svg" width="172" height="64" style="grid-area: 1 / 1 / -1 / -1">
            <g>
              <g>
                <path
                  mode="delta"
                  fill="currentColor"
                  d="m1,1h171l-36,24h-99l-36,-24z"
                  data-automation-id="position-top-button"
                  aria-label="Position top button"
                  class="tb-path-color"
                ></path>
              </g>
            </g>
            <g>
              <g>
                <path
                  mode="delta"
                  fill="currentColor"
                  d="m171,1v63l-36,-24v-15l36,-24z"
                  data-automation-id="position-right-button"
                  aria-label="Position right button"
                  class="lr-path-color"
                ></path>
              </g>
            </g>
            <g>
              <g>
                <path
                  mode="delta"
                  fill="currentColor"
                  d="m1,63h171l-36,-24h-99l-36,24z"
                  data-automation-id="position-bottom-button"
                  aria-label="Position bottom button"
                  class="tb-path-color"
                ></path>
              </g>
            </g>
            <g>
              <g>
                <path
                  mode="delta"
                  fill="currentColor"
                  d="m1,1v63l36,-24v-15l-36,-24z"
                  data-automation-id="position-left-button"
                  aria-label="Position left button"
                  class="lr-path-color"
                ></path>
              </g>
            </g>
            <clipPath id="position-outer">
              <rect
                x="0"
                y="0"
                width="172"
                height="64"
                fill="transparent"
                rx="2"
                ry="2"
                style="pointer-events: none"
              ></rect>
            </clipPath>
            <rect
              clip-path="url(#position-outer)"
              x="0"
              y="0"
              width="172"
              height="64"
              fill="transparent"
              rx="2"
              ry="2"
              class="stroke"
              style="pointer-events: none; stroke-width: 2px"
            ></rect>
            <clipPath id="position-inner">
              <rect
                x="36"
                y="24"
                width="100"
                height="16"
                fill="transparent"
                rx="2"
                ry="2"
                style="pointer-events: none"
              ></rect>
            </clipPath>
            <rect
              clip-path="url(#position-inner)"
              x="36"
              y="24"
              width="100"
              height="16"
              fill="transparent"
              rx="2"
              ry="2"
              class="stroke"
              style="pointer-events: none; stroke-width: 2px"
            ></rect>
          </svg>
          <div
            :class="[
              'direction',
              'top',
              {
                'is-setting': getSettingFlag(POSITION_PROPERTY.Top),
                'is-show': state.show && state.className === POSITION_PROPERTY.Top
              }
            ]"
            @click="clickDirection(POSITION_PROPERTY.Top, $event)"
          >
            <span>{{ getDirectionText(POSITION_PROPERTY.Top) }}</span>
          </div>
          <div
            :class="[
              'direction',
              'right',
              {
                'is-setting': getSettingFlag(POSITION_PROPERTY.Right),
                'is-show': state.show && state.className === POSITION_PROPERTY.Right
              }
            ]"
            @click="clickDirection(POSITION_PROPERTY.Right, $event)"
          >
            <span>{{ getDirectionText(POSITION_PROPERTY.Right) }}</span>
          </div>
          <div
            :class="[
              'direction',
              'bottom',
              {
                'is-setting': getSettingFlag(POSITION_PROPERTY.Bottom),
                'is-show': state.show && state.className === POSITION_PROPERTY.Bottom
              }
            ]"
            @click="clickDirection(POSITION_PROPERTY.Bottom, $event)"
          >
            <span>{{ getDirectionText(POSITION_PROPERTY.Bottom) }}</span>
          </div>
          <div
            :class="[
              'direction',
              'left',
              {
                'is-setting': getSettingFlag(POSITION_PROPERTY.Left),
                'is-show': state.show && state.className === POSITION_PROPERTY.Left
              }
            ]"
            @click="clickDirection(POSITION_PROPERTY.Left, $event)"
          >
            <span>{{ getDirectionText(POSITION_PROPERTY.Left) }}</span>
          </div>
        </div>
      </div>
      <div class="relative-wrap">
        <div class="target">
          <svg-icon name="target"></svg-icon>
          <span>{{ state.relativeTo }}</span>
        </div>
        <div class="relative">
          <span>Relative to</span>
        </div>
        <numeric-select
          :name="getProperty(POSITION_PROPERTY.ZIndex).name"
          :numericalText="getProperty(POSITION_PROPERTY.ZIndex).text"
          suffix="-"
          @update="updateStyle"
        />
        <span
          :class="['index', { 'is-setting': getSettingFlag(POSITION_PROPERTY.ZIndex) }]"
          @click="openSetting(POSITION_PROPERTY.ZIndex, $event)"
          >z-Index</span
        >
      </div>
    </div>
  </div>
  <modal-mask v-if="state.showModal" @close="state.showModal = false">
    <reset-button @reset="reset" />
  </modal-mask>
  <modal-mask v-if="state.showDirectionModal" @close="closeDirectionModal">
    <spacing-setting :property="state.property" @update="update"></spacing-setting>
  </modal-mask>
</template>

<script>
/* metaService: engine.setting.styles.PositionGroup */
import { reactive, watchEffect } from 'vue'
import { Tooltip } from '@opentiny/vue'
import { SelectConfigurator } from '@opentiny/tiny-engine-configurator'
import { push } from '@opentiny/vue-renderless/common/array'
import ModalMask, { useModal } from '../inputs/ModalMask.vue'
import SpacingSetting from '../spacing/SpacingSetting.vue'
import ResetButton from '../inputs/ResetButton.vue'
import NumericSelect from '../inputs/NumericSelect.vue'
import { useProperties } from '../../js/useStyle'
import { POSITION_PROPERTY } from '../../js/styleProperty'

export default {
  components: {
    ModalMask,
    ResetButton,
    SelectConfigurator,
    NumericSelect,
    SpacingSetting,
    TinyTooltip: Tooltip
  },

  props: {
    style: {
      type: Object,
      default: () => ({})
    }
  },

  emits: ['update'],
  setup(props, { emit }) {
    let activedName = ''
    const selectOptions = [
      {
        label: 'Static-默认定位',
        value: 'static'
      },
      {
        label: 'Relative-相对定位',
        value: 'relative'
      },
      {
        label: 'Absolute-绝对定位',
        value: 'absolute'
      },
      {
        label: 'Fixed-固定定位',
        value: 'fixed'
      },
      {
        label: 'Sticky-粘性定位',
        value: 'sticky'
      }
    ]

    const positionOptions = [
      {
        tip: 'Top left',
        icon: 'position-top-left',
        value: '0% auto auto 0%'
      },
      {
        tip: 'Top right',
        icon: 'position-top-right',
        value: '0% 0% auto auto'
      },
      {
        tip: 'Bottom left',
        icon: 'position-bottom-left',
        value: 'auto auto 0% 0%'
      },
      {
        tip: 'Bottom right',
        icon: 'position-bottom-right',
        value: 'auto 0% 0% auto'
      },
      {
        tip: 'Left',
        icon: 'position-left',
        value: '0% auto 0% 0%'
      },
      {
        tip: 'Right',
        icon: 'position-right',
        value: '0% 0% 0% auto'
      },
      {
        tip: 'Bottom',
        icon: 'position-bottom',
        value: 'auto 0% 0% 0%'
      },
      {
        tip: 'Top',
        icon: 'position-top',
        value: '0% 0% auto 0%'
      },
      {
        tip: 'Full',
        icon: 'position-all',
        value: '0%'
      }
    ]

    const state = reactive({
      showModal: false,
      showSetting: false,
      showSettingIcon: false,
      showDirectionModal: false,
      show: false,
      className: '',
      selectedIndex: -1,
      selectValue: 'static',
      relativeTo: '404 Content Wrap',
      activeArr: ['inset'],
      directionText: {
        top: '',
        right: '',
        bottom: '',
        left: ''
      },
      property: {
        type: '',
        name: '',
        value: ''
      }
    })
    watchEffect(() => {
      state.selectValue = props.style?.position || 'static'
    })
    const { setPosition } = useModal()

    const updateStyle = (property) => {
      emit('update', property)
    }

    const reset = () => {
      if (activedName === 'position') {
        state.selectValue = 'static'
        state.showSetting = false
        state.selectedIndex = -1
        state.activeArr?.forEach((name) => {
          updateStyle({ [name]: null })
        })
      }

      updateStyle({ [activedName]: null })
      state.showModal = false
    }

    const { getProperty, getSettingFlag, getPropertyValue, getPropertyText } = useProperties({
      names: Object.values(POSITION_PROPERTY),
      parseNumber: true
    })

    const selectPosition = (val) => {
      if (val) {
        state.selectValue = val
        state.showSetting = val !== 'static'
        state.showSettingIcon = val === 'absolute' || val === 'fixed'
        state.relativeTo = val === 'relative' ? 'Itself' : '404 Content Wrap'
        updateStyle({ [POSITION_PROPERTY.Position]: val })
      }
    }

    const selectInsetValue = (item, index) => {
      let directionArr = []

      directionArr = item.value === 'Full' ? ['0%', '0%', '0%', '0%'] : item.value.split(' ')
      Object.keys(state.directionText).forEach((key, index) => {
        state.directionText[key] = directionArr[index]
      })
      state.selectedIndex = index
      updateStyle({ [POSITION_PROPERTY.Inset]: item.value })
    }

    const openSetting = (name, event) => {
      if (getSettingFlag(name)) {
        activedName = name
        setPosition(event)
        state.showModal = true
      }
    }

    const openDirectionSetting = (type, styleName) => {
      state.property = {
        type,
        name: styleName,
        value: getPropertyValue(styleName)
      }

      state.showDirectionModal = true
    }

    const getDirectionText = (name) => state.directionText[name] || getPropertyText(name) || 'auto'

    const clickDirection = (styleName, event) => {
      state.activeArr = push(state.activeArr, styleName)
      state.className = styleName
      state.show = true
      setPosition(event)
      openDirectionSetting(POSITION_PROPERTY.Position, styleName)
    }

    const closeDirectionModal = () => {
      state.show = false
      state.showDirectionModal = false
    }

    const update = (property) => {
      state.property.value = property[state.property.name]
      emit('update', property)
    }

    return {
      state,
      POSITION_PROPERTY,
      selectOptions,
      positionOptions,
      reset,
      update,
      updateStyle,
      getProperty,
      getSettingFlag,
      selectPosition,
      selectInsetValue,
      openSetting,
      getDirectionText,
      clickDirection,
      closeDirectionModal
    }
  }
}
</script>

<style lang="less" scoped>
.position-group {
  display: grid;
  gap: 8px;
  grid-template-columns: 48px 1fr;
  align-items: center;

  span {
    padding: 2px;
  }

  .position-label {
    color: var(--te-styles-common-text-color-secondary);
  }
  .position-dropdown {
    grid-column: 1 / -1;
  }
  .tooltip-wrap,
  .setting-wrap {
    grid-column: 1 / -1;
    align-items: center;
    display: grid;
    gap: 8px;
    grid-template-columns: 48px 1fr;
    padding: 0px;
  }
  .tooltip-icon {
    grid-area: 1 / 2 / -1 / 3;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .tooltip-wrap {
    margin-bottom: 8px;
  }
  .setting-wrap {
    .setting {
      grid-area: 1 / 2 / -1 / 3;
      display: grid;
      grid-template-columns: 36px 1fr 36px;
      grid-template-rows: 24px minmax(16px, 1fr) 24px;
      justify-items: center;
      width: 172px;
      height: 64px;
    }
    .direction {
      cursor: default;
      user-select: none;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 10px;
      font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
        'Helvetica Neue', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif;
      font-weight: 400;
      line-height: 10px;
      letter-spacing: -0.2px;
      display: flex;
      color: var(--te-styles-common-text-color-primary);
      background: transparent;
      padding: 2px;
      margin-left: -2px;
      border-radius: 2px;
      max-width: 100%;
      box-sizing: content-box;
      place-self: center;
      position: relative;
      opacity: 1;
      align-items: center;
      justify-content: center;
      &.is-setting {
        background-color: var(--te-styles-common-setting-bg-color);
      }

      &.is-show {
        background-color: var(--te-styles-position-direction-bg-color);
      }
    }
    .top {
      grid-area: 1 / 2 / 2 / 3;
    }
    .right {
      grid-area: 2 / 3 / 3 / 4;
    }
    .bottom {
      grid-area: 3 / 2 / 4 / 3;
    }
    .left {
      grid-area: 2 / 1 / 3 / 2;
    }
  }
  .icon-wrap {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    width: 20px;
    height: 20px;
    font-size: 16px;
    &:hover {
      background-color: var(--te-styles-common-bg-color-hover);
    }
    &.selected {
      background-color: var(--te-styles-common-bg-color-active);
    }
  }
  .relative-wrap {
    grid-column: 1 / -1;
    align-items: center;
    display: grid;
    gap: 4px 8px;
    grid-template-columns: 48px 1fr 1fr 1fr;
    margin-top: 8px;
    .target {
      height: 28px;
      background-color: var(--te-styles-position-relative-bg-color);
      color: var(--te-styles-common-text-color-primary);
      grid-column: 2 / span 2;
      align-items: center;
      display: grid;
      gap: 4px;
      grid-template-columns: 16px auto 1fr;
      padding: 0px 4px;
      .svg-icon {
        font-size: 16px;
      }
      span {
        display: inline-block;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
    .relative {
      grid-column: 2 / span 2;
      justify-self: center;
    }
    .style-numeric {
      grid-column-start: 4;
      grid-row-start: 1;
    }
    .index {
      grid-column-start: 4;
      grid-row-start: 2;
      justify-self: center;
    }
  }
  .is-setting {
    span {
      cursor: pointer;
      border-radius: 2px;
      color: var(--te-styles-common-setting-text-color);
      background-color: var(--te-styles-common-setting-bg-color);
    }
  }
  .lr-path-color {
    color: var(--te-styles-position-relative-lr-bg-color);
    cursor: default;
    &:hover {
      color: var(--te-styles-position-relative-lr-bg-color-hover);
    }
  }

  .tb-path-color {
    color: var(--te-styles-position-relative-tb-bg-color);
    cursor: default;
    &:hover {
      color: var(--te-styles-position-relative-tb-bg-color-hover);
    }
  }

  .stroke {
    stroke: var(--te-styles-position-relative-border-color);
  }
}
</style>