<script>
import { inject } from 'vue'
import { Options, Vue } from "vue-class-component";
import { useFocusHub } from 'jsview';
import Button from "./Button.vue";

@Options({
  props: {
    style: { type: Object, default: {width:1400,height:50} },
  },
  components: {
    Button,
  },
})

class Controllor extends Vue {
  constructor(props) {
    super(props);

    this.mediaCtrl = inject('mediaCtrl');
    this.mediaTime = inject('mediaTime');
    this.mediaStatus = inject('mediaStatus');
    this.videoCtrl = inject('videoCtrl');

    this.buttonList = this.getButtonList();

    this.playbackRateData = [
      { name: "1.0", playbackRate: 1.0 },
      { name: "2.0", playbackRate: 2.0 },
      { name: "4.0", playbackRate: 4.0 },
      { name: "0.5", playbackRate: 0.5 },
      { name: "0.25", playbackRate: 0.25 },
      { name: "-1.0", playbackRate: -1.0 },
    ];
    this.playbackRateIndex = 0;

    this.objectFitData = [
      { name: "contain-horizontal", objectFit: "contain", width: 1200 },
      { name: "contain-vertical", objectFit: "contain", width: 400 },
      { name: "fill", objectFit: "fill", width: 1200 },
      { name: "cover-horizontal", objectFit: "cover", width: 1200 },
      { name: "cover-vertical", objectFit: "cover", width: 400 },
    ];
    this.objectFitIndex = 0;

    this.buttonRowCount = 7;
    this.focusedItemIndex = 0;
  }

  created() {
    this.setPlaybackRate(0);
    this.setObjectFit(0);
  }

  setup() {
    return {
      focusHub: useFocusHub()
    }
  }

  onKeyDown(ev) {
    // 8:Backspace, 27:Escape, 10000:盒子返回键
    if(ev.keyCode == 8 || ev.keyCode == 27 || ev.keyCode == 10000) {
      this.$router?.go(-1); // 有router时，回退
      return true;
    }

    let focusStep = 0;
    let autoFindNext = false;
    switch (ev.keyCode) {
      case 37: // Left
        focusStep = -1;
        autoFindNext = true;
        break;
      case 39: // Right
        focusStep = 1;
        autoFindNext = true;
        break;
      case 38: // Up
        focusStep = -this.buttonRowCount;
        break;
      case 40: // Down
        focusStep = this.buttonRowCount;
        break;
      default:
        break;
    }

    const buttonData = this.getButtonData();
    const buttonAllCount = this.buttonRowCount * 2;
    let newFocusIdx = this.focusedItemIndex;
    let hasNextFocusItem = false;
    while(true) {
      newFocusIdx = (newFocusIdx + focusStep + buttonAllCount) % buttonAllCount;
      if(!buttonData[newFocusIdx]?.name) {
        if(autoFindNext) {
          continue;
        } else {
          break;
        }
      }

      hasNextFocusItem = true;
      break;
    };

    if(hasNextFocusItem) {
      this.focusHub.setFocus('controllor.' + 'btn-' + newFocusIdx);
      this.focusedItemIndex = newFocusIdx;
      return true;
    }

    return false;
  }

  getButtonList() {
    const buttonList = [{ 
        name: "To AudioMode",
        onClick: () => {
          this.mediaCtrl.type = (this.mediaCtrl.type == 'audio' ? 'video' : 'audio');
          this.mediaCtrl.autoplay = true; // 自动播放
          this.mediaCtrl.mute = false; // 关闭静音
          this.mediaCtrl.loop = false; // 关闭循环
          this.mediaTime.currentTime = 0;
          this.mediaTime.duration = 0;
          this.mediaCtrl.playTrigger = 0; // 停止并初始化播放
          this.setPlaybackRate(0);
          this.setObjectFit(0);
          this.videoCtrl.visibility = 'visible';
          if(this.mediaCtrl.type == 'audio') {
            this.mediaStatus.objectFit = '';
            this.videoCtrl.visibility = '';
          }
 
          this.focusedItemIndex = 0;
        },
        isModeButton: true,
      }, {
        name: "Play",
        onClick: () => {
          this.mediaCtrl.playTrigger = ++this.mediaCtrl.playTrigger; /* 为了触发ref更新 */
        },
        isPlayButton: true,
      }, {
        name: "Rewind <<",
        onClick: () => {
          this.mediaCtrl.seek = (this.mediaCtrl.seek !== -10 ? -10 : -10.1/* 为了触发ref更新 */); 
        }
      }, {
        name: "Forward >>",
        onClick: () => {
          this.mediaCtrl.seek = (this.mediaCtrl.seek !== +10 ? +10 : +10.1/* 为了触发ref更新 */); 
        }
      }, {
        name: "Reload",
        onClick: () => {
          this.mediaCtrl.loadTrigger = ++this.mediaCtrl.loadTrigger; /* 为了触发ref更新 */
        },
      }, {
        name: "Loop Off",
        onClick: () => {
          this.mediaCtrl.loop = !this.mediaCtrl.loop;
        },
        isLoopButton: true,
      }, {
        name: "ObjectFit",
        onClick: this.setObjectFit.bind(this)
      }, {
        // 空，按钮对其用
      }, {
        name: "Mute Off",
        onClick: () => {
          this.mediaCtrl.mute = !this.mediaCtrl.mute;
        },
        isMuteButton: true,
      }, {
        name: "Volume",
        onClick: () => {
          this.mediaCtrl.volume = (this.mediaCtrl.volume !== 0.2 ? 0.2 : 0.21/* 为了触发ref更新 */); 
        }
      }, {
        name: "Rate",
        onClick: this.setPlaybackRate.bind(this)
      }, {
        name: "Visibility",
        onClick: () => {
          this.videoCtrl.visibility = (this.videoCtrl.visibility != 'visible' ? 'visible' : 'hidden');
        },
      },
    ];

    return buttonList;
  }

  getButtonData() {
    const buttonWidth = 158;
    const buttonHeight = 40;
    const buttonSpacing = 15;

    let data = [];
    const length = this.buttonList.length;
    for(let idx = 0; idx < length; idx++) {
      let button = this.buttonList[idx];
      if(this.mediaCtrl.type == 'audio'
      && (button.name == 'ObjectFit'
      || button.name == 'Visibility')) { // 只有video方式可以做ObjectFit和visibility
        button = {};
      }

      data.push({
        ...button,
        layout: {
          left: (buttonWidth + buttonSpacing) * (idx % this.buttonRowCount),
          top: (buttonHeight + buttonSpacing) * Math.floor(idx / this.buttonRowCount),
          width: buttonWidth,
          height: buttonHeight,
        }
      });
    }
    return data;
  }

  setPlaybackRate(index) {
    if(typeof index === 'number') {
      this.playbackRateIndex = index;
    } else {
      this.playbackRateIndex = (++this.playbackRateIndex % this.playbackRateData.length);
    }
    const data = this.playbackRateData[this.playbackRateIndex];
    this.mediaStatus.playbackRate = data.name;
    this.mediaCtrl.playbackRate = data.playbackRate;
  }

  setObjectFit(index) {
    if(typeof index === 'number') {
      this.objectFitIndex = index;
    } else {
      this.objectFitIndex = (++this.objectFitIndex % this.objectFitData.length);
    }
    const data = this.objectFitData[this.objectFitIndex];
    this.mediaStatus.objectFit = data.name;
    this.videoCtrl.objectFit = data.objectFit;
    this.videoCtrl.layout = {
      left: (1280 - data.width) / 2, top: 20,
      width: data.width, height: 500,
    }
  }

  getShowName(item) {
    if(item.isModeButton) {
      return this.mediaCtrl.type == 'audio' ? "To VideoMode" : "To AudioMode";
    } else if(item.isPlayButton) {
      return this.mediaStatus.playing ? 'Pause' : 'Play'
    } else if(item.isLoopButton) {
      return this.mediaCtrl.loop ? 'Loop Off' : 'Loop On'
    } else if(item.isMuteButton) {
      return this.mediaCtrl.mute ? 'Mute Off' : 'Mute On'
    }

    return item.name;
  }
}

export default Controllor;
</script>

<template>
<div :style="style" :key="mediaCtrl.type + mediaCtrl.loop + mediaCtrl.mute + mediaStatus.playing">
  <jsv-focus-block namespace="controllor" :onKeyDown="onKeyDown">
    <div v-for="(item,index) in getButtonData()" :key="index">
      <Button v-if="item.name"
          :style="{ left: item.layout.left, top: item.layout.top,
                    width:item.layout.width, height:item.layout.height }"
          :autoFocus="index === focusedItemIndex"
          :name="'btn-' + index"
          :onClick="item.onClick"
      >
        {{ getShowName(item) }}
      </Button>
    </div>
  </jsv-focus-block>
</div>
</template>

<style scoped>
</style>
