<template>
  <div class="l-flex--col c-viewer">
    <audio
      v-if="bgmUrl"
      ref="audio"
      :src="bgmUrl"
      :muted.prop="muted"
      autoplay
      @ended="onAudioEnded"
      @error="onAudioError"
    />
    <div class="l-flex__none l-flex--row c-viewer__header">
      <i
        class="c-viewer__shortcut el-icon-arrow-left u-bold u-pointer"
        @click="onBack"
      />
      <span class="c-viewer__name u-bold u-ellipsis">{{ program.name }}</span>
      <span class="c-sibling-item">{{ program.resolutionRatio }}</span>
      <div
        v-if="hasAudio"
        class="c-sibling-item c-viewer__shortcut u-pointer"
        @click="toggleMute"
      >
        <volume :muted="muted" />
      </div>
      <div
        v-if="hasNext"
        class="c-sibling-item c-viewer__shortcut u-pointer"
        @click="switchBgm"
      >
        <i class="o-next" />
      </div>
    </div>
    <div class="l-flex__fill l-flex">
      <div class="l-flex__none l-flex--col c-viewer__asserts">
        <div class="l-flex__none l-flex--row c-viewer__count has-padding--h">
          <span class="l-flex__auto u-bold">素材</span>
          <span class="l-flex__none c-viewer__count--info">{{ count }}</span>
        </div>
        <el-scrollbar
          class="c-viewer__scrollbar"
          native
        >
          <div class="c-viewer__list">
            <div
              v-for="widget in layers"
              ref="widgetElements"
              :key="widget.id"
              class="o-layer"
              :class="{ active: widget.id === selectedWidgetId }"
              @click="onWidgetClick(widget, $event)"
            >
              <widget-shortcut
                :widget="widget"
                @view="onView"
              />
            </div>
            <div
              v-if="hasRootAssets"
              ref="rootElement"
              key="root"
              class="o-layer"
              :class="{ active: !selectedWidgetId }"
              @click="onRootClick"
            >
              <widget-shortcut
                :widget="node"
                :custom-style="backgroundStyles"
                source-key="bgm"
                background
                @view="onView"
              />
            </div>
          </div>
        </el-scrollbar>
      </div>
      <div
        ref="wrapper"
        class="c-viewer__content"
        @click="onRootClick"
      >
        <div
          class="l-flex__fill c-viewer__canvas has-bg"
          :style="[transformStyles, styles]"
        >
          <div
            class="c-viewer__background has-bg"
            :style="backgroundStyles"
          />
          <widget
            v-for="item in widgets"
            :key="item.id"
            :class="{ 'breathe-inset': item.id === selectedWidgetId }"
            :node="item"
            @click.native="onWidgetClick(item, $event)"
          />
        </div>
      </div>
    </div>
    <preview-dialog
      ref="previewDialog"
      @close="onClose"
    />
  </div>
</template>

<script>
import { AssetType } from '@/constant'
import { WidgetType } from './core/constant'
import mixin from './mixin'
import Widget from './core/widget/WidgetViewer.vue'

export default {
  name: 'BigScreenViewer',
  components: {
    Widget
  },
  mixins: [mixin],
  data () {
    return {
      selectedWidget: null
    }
  },
  computed: {
    layers () {
      return this.widgets.filter(this.hasAssets).slice().reverse()
    },
    count () {
      if (this.node) {
        return this.node.bgm.length + this.node.backgroundImage.length + this.layers.reduce((total, { sources }) => total + sources.length, 0)
      }
      return 0
    },
    selectedWidgetId () {
      return this.selectedWidget?.id
    },
    hasRootAssets () {
      if (this.node) {
        const { backgroundImage, bgm } = this.node
        return backgroundImage.length > 0 || bgm.length > 0
      }
      return false
    }
  },
  watch: {
    selectedWidget () {
      this.node && setTimeout(() => {
        if (this.selectedWidget) {
          this.$refs.widgetElements?.find(element => element.classList.contains('active'))?.scrollIntoView({ behavior: 'smooth', block: 'start' })
        } else if (this.hasRootAssets) {
          this.$refs.rootElement.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }
      })
    }
  },
  methods: {
    hasAssets (widget) {
      switch (widget.type) {
        case WidgetType.MEDIA:
        case WidgetType.IMAGE:
        case WidgetType.VIDEO:
          return true
        default:
          return false
      }
    },
    onWidgetClick (widget, evt) {
      if (this.hasAssets(widget)) {
        evt.stopPropagation()
        if (!this.selectedWidget || this.selectedWidget.id !== widget.id) {
          this.selectedWidget = widget
        }
      }
    },
    onRootClick () {
      this.selectedWidget = null
    },
    onView (source) {
      this.$muted = this.muted
      switch (source.type) {
        case AssetType.VIDEO:
        case AssetType.AUDIO:
          if (!this.muted) {
            this.muted = true
          }
          break
        default:
          break
      }
      this.$refs.previewDialog.show(source)
    },
    onClose () {
      this.muted = this.$muted
    }
  }
}
</script>

<style lang="scss" scoped>
.c-viewer {
  height: 100%;
  min-width: 800px;
  min-height: 600px;
  overflow: hidden;

  &__header {
    height: 53px;
    padding: 0 24px 0 10px;
    color: $black;
    font-size: 12px;
    line-height: 1;
    border-bottom: 1px solid $border;
    background-color: #fff;
  }

  &__shortcut {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    width: 36px;
    height: 36px;
    font-size: 18px;
    border-radius: 50%;
    transition: background-color 0.4s;

    &:hover {
      background-color: $gray--light;
    }

    &:active {
      background-color: $gray;
    }
  }

  &__name {
    max-width: 400px;
    padding: 0 $spacing 0 6px;
    font-size: 18px;
  }

  &__asserts {
    width: 145px;
    border-right: 1px solid $border;
    background-color: #fff;
  }

  &__count {
    height: 48px;
    color: $black;
    font-size: 16px;
    line-height: 1;
    background-color: #e8eaee;

    &--info {
      color: $info--dark;
      font-size: 12px;
    }
  }

  &__scrollbar {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    min-height: 0;

    ::v-deep {
      .el-scrollbar__wrap {
        flex: 1 1 0;
        min-height: 0;
        margin-bottom: 0 !important;
      }
    }
  }

  &__list {
    padding: 10px;
  }

  &__content {
    flex: 1 0 0;
    min-width: 0;
    min-height: 0;
  }

  &__canvas {
    position: relative;
    background-color: #000;
    overflow: hidden;
  }

  &__background {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: currentColor;
    z-index: -1;
  }
}

.o-layer {
  color: $black;
  user-select: none;
  border-radius: $radius;
  background-color: #f4f7f8;
  overflow: hidden;
  cursor: pointer;

  & + & {
    margin-top: 10px;
  }

  &.active {
    color: #fff;
    outline: 2px solid $blue;
    background-color: $blue;
  }
}

.breathe-inset::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  animation: breathe-inset 1s ease-in-out infinite alternate;
}

@keyframes breathe-inset {
  0% {
    box-shadow: inset 0 0 20px 30px rgba($blue, 0.5);
  }
  100% {
    box-shadow: inset 0 0 60px 30px $blue;
  }
}
</style>
