<template>
  <div class="Metronome">
    <div class="MetronomeBox">
      <div class="headTools">
        <img
          src="./imgs/minMet.png"
          @click="
            () => {
              emits('windowMet');
            }
          "
        />
        <img
          src="./imgs/closeMet.png"
          @click="
            () => {
              emits('closeMet');
            }
          "
        />
      </div>
      <div class="beatWrap">
        <div
          class="dot"
          ref="dotDom"
          @mousedown="handleDotMousedown"
          @touchstart="handleDotTouchstart"
        ></div>
        <div class="round"></div>
        <canvas
          ref="mycanvasDom"
          class="mycanvas"
          width="252"
          height="252"
          @click="handleEventCanvas"
        ></canvas>
        <div class="beatCon">
          <img
            class="optImg"
            src="./imgs/jia.png"
            @click="
              () => {
                if (speedNum < 200) {
                  speedNum++;
                }
              }
            "
          />
          <div class="optMid">
            <img class="optImg" src="./imgs/yin.png" />
            <n-input-number
              :disabled="true"
              placeholder=""
              :value="speedNum"
              :show-button="false"
              @update:value="(num:number)=>{
                if(num){
                  if(num<=50){
                    speedNum=50
                  }else if(num>=200){
                    speedNum=200
                  }else{
                    speedNum=num
                  }
                }
              }"
            />
          </div>
          <img
            class="optImg"
            src="./imgs/jian.png"
            @click="
              () => {
                if (speedNum > 50) {
                  speedNum--;
                }
              }
            "
          />
        </div>
      </div>
      <div class="selectCon">
        <n-select
          v-model:value="beatVal"
          :options="beatValOpt"
          :show-checkmark="false"
          :show-arrow="false"
          :placement="'top'"
          :render-tag="
            ({ option }:any) => {
              return h('div',{class:'beatName'},[h('div',option.labelHide),h('div','拍')])
            }
          "
          :render-label="
            (option:any) => {
              return h('div', option.labelHide);
            }
          "
        ></n-select>
        <n-select
          class="beatSymbolSel"
          v-model:value="beatSymbol"
          :options="beatSymbolOpt"
          :show-checkmark="false"
          :show-arrow="false"
          :placement="'top'"
          :render-tag="
            ({ option }:any) => {
              return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
            }
          "
          :render-label="
            (option:any) => {
              return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
            }
          "
        ></n-select>
      </div>
      <div class="sliderList">
        <img src="./imgs/sound.png" alt="" />
        <NSlider v-model:value="volumeNum" :step="1" :tooltip="false">
          <template #thumb>
            <img class="thumbDot" src="./imgs/dotBtn.png" alt="" />
          </template>
        </NSlider>
        <span class="sliderText">{{ volumeNum }}</span>
      </div>
      <div v-if="playState === 'pause'" class="playBtn" @click="startPlay">
        <span>播放</span>
        <img src="./imgs/playtBtn.png" />
      </div>
      <div v-else class="playBtn" @click="pausePlay">
        <span>暂停</span>
        <img class="pauseImg" src="./imgs/pauseBtn.png" />
      </div>
    </div>
    <Dragbom></Dragbom>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, h, watch } from 'vue';
import { NInputNumber, NSelect, NSlider } from 'naive-ui';
import useMetronome from './useMetronome';
import Dragbom from '@/hooks/useDrag/dragbom';
import { getCachePos, setCachePos } from './useMetronome';
import { useUserStore } from '@/store/modules/users';

const users = useUserStore();
const emits = defineEmits<{
  (e: 'windowMet'): void;
  (e: 'closeMet'): void;
  (e: 'playStateChange', state: 'play' | 'pause'): void;
}>();

/* dom */
const mycanvasDom = ref<HTMLCanvasElement>();
const dotDom = ref<HTMLElement>();
/* select */
const beatVal = ref('1');
const beatValOpt = [
  {
    label: '',
    labelHide: '0',
    value: '0',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '1',
    value: '1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '2',
    value: '1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '3',
    value: '1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '4',
    value: '1-1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '5',
    value: '1-1-1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '6',
    value: '1-1-1-1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '7',
    value: '1-1-1-1-1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '8',
    value: '1-1-1-1-1-1-1-1',
    class: 'beatValOptItem'
  },
  {
    label: '',
    labelHide: '9',
    value: '1-1-1-1-1-1-1-1-1',
    class: 'beatValOptItem'
  }
];
const beatSymbol = ref('1');
const beatSymbolOpt = [
  {
    label: '',
    labelHide: '1',
    value: '1',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '2',
    value: '0.5-0.5',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '3',
    value: '0.3333333-0.3333333-0.3333333',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '4',
    value: '0.25-0.25-0.25-0.25',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '5',
    value: '0.6666666-0.3333333',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '6',
    value: '0.75-0.25',
    class: 'beatSymbolOptItem'
  },
  {
    label: '',
    labelHide: '7',
    value: '0.5-0.25-0.25',
    class: 'beatSymbolOptItem'
  }
];
const { volumeNum, playState, speedNum, startPlay, pausePlay } = useMetronome(
  beatVal,
  beatSymbol
);

onMounted(() => {
  const cachePos = getCachePos(users.info.id);
  if (cachePos) {
    beatVal.value = cachePos.beatVal;
    beatSymbol.value = cachePos.beatSymbol;
    volumeNum.value = cachePos.volumeNum;
    speedNum.value = cachePos.speedNum;
  }
  /*  n-input-number 有bug  input-props设置maxlength不上去 */
  const iptDoms = document.querySelector(
    '.Metronome .MetronomeBox .optMid .n-input__input-el'
  );
  iptDoms?.setAttribute('maxlength', '3');
  getCircleBar(speedToScalc(speedNum.value));
});

onUnmounted(() => {
  setCachePos(users.info.id, {
    beatVal: beatVal.value,
    beatSymbol: beatSymbol.value,
    volumeNum: volumeNum.value,
    speedNum: speedNum.value
  });
});

watch(playState, () => {
  emits('playStateChange', playState.value);
});
watch(speedNum, () => {
  if (playState.value === 'play') {
    pausePlay();
  }
  getCircleBar(speedToScalc(speedNum.value));
});
watch([beatVal, beatSymbol], () => {
  if (playState.value === 'play') {
    pausePlay();
  }
});
function speedToScalc(speed: number) {
  return ((speed - 50) / 150) * 100;
}
function scalcToSpeed(scalc: number) {
  return Math.round((scalc * 150) / 100 + 50);
}
const handleEventCanvas = (e: MouseEvent | TouchEvent) => {
  const circle = mycanvasDom.value!.getBoundingClientRect();
  const centerX = circle.left + circle.width / 2;
  const centerY = circle.top + circle.height / 2;
  const event = isTouchEvent(e) ? e.touches[0] : e;
  const angle = Math.atan2(event.clientY - centerY, event.clientX - centerX);
  const percentage = (angle * (180 / Math.PI) + 180) / 360;
  const scalc = Math.round(percentage * 100) - 25;
  speedNum.value = scalcToSpeed(scalc < 0 ? 100 + scalc : scalc);
};
function handleDotMousedown() {
  function onMouseup() {
    document.removeEventListener('mousemove', onMousemove);
    document.removeEventListener('mouseup', onMouseup);
  }
  document.addEventListener('mousemove', onMousemove);
  document.addEventListener('mouseup', onMouseup);
}
function handleDotTouchstart() {
  function onTouchend() {
    document.removeEventListener('touchmove', onTouchmove);
    document.removeEventListener('touchend', onTouchend);
  }
  document.addEventListener('touchmove', onTouchmove);
  document.addEventListener('touchend', onTouchend);
}
function onMousemove(e: MouseEvent) {
  handleEventCanvas(e);
}
function onTouchmove(e: TouchEvent) {
  handleEventCanvas(e);
}
// 根据百分比画圆
function getCircleBar(steps: number) {
  const radius = 121; //半径
  const colorList = ['#51DBFF', '#009FFF'];
  const mycanvas = mycanvasDom.value!;
  const ctx = mycanvas.getContext('2d')!;
  // 每次进来清空画布
  ctx.clearRect(0, 0, mycanvas.width, mycanvas.height);
  //找到画布的中心点
  const canvasX = mycanvas.width / 2;
  const canvasY = mycanvas.height / 2;
  //进度条是100%，所以要把一圈360度分成100份
  const progress = (Math.PI * 2) / 100;
  const ao = -Math.PI / 2 + steps * progress;
  const x1 = radius + Math.cos(ao) * radius;
  const y1 = radius + Math.sin(ao) * radius;
  // 这里开始算坐标
  dotDom.value!.style.left = x1 - 7 + 'Px';
  dotDom.value!.style.top = y1 - 7 + 'Px';
  // 绘制渐变色
  const gradientDirection = {
    x1: 0,
    y1: 0,
    x2: radius * 2, // 半径*2
    y2: 0
  };
  gradientDirection.y2 = radius * 2;
  const gradient = ctx.createLinearGradient(
    gradientDirection.x1,
    gradientDirection.y1,
    gradientDirection.x2,
    gradientDirection.y2
  );
  colorList.map((color, index) => {
    gradient.addColorStop(index, color);
  });
  ctx.strokeStyle = gradient;
  ctx.lineWidth = 10;
  ctx.save();
  ctx.beginPath();
  ctx.arc(
    canvasX,
    canvasY,
    radius,
    -Math.PI / 2,
    -Math.PI / 2 + steps * progress,
    false
  );
  ctx.stroke();
  ctx.closePath();
  ctx.restore();
}
function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {
  return window.TouchEvent && e instanceof window.TouchEvent;
}
defineExpose({
  startPlay,
  pausePlay,
  speedNum,
  beatSymbol
});
</script>

<style lang="less" scoped>
.Metronome {
  width: 565Px;
  height: 554Px;
  background: url('./imgs/bg.png') no-repeat;
  background-size: 100% 100%;
  padding: 26Px 26Px 0;
  &:deep(.bom_drag) {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 76Px;
    padding: 0 28Px;
    & > div {
      width: 40Px;
      height: 40Px;
      border-radius: 0 0 18Px 0;
      &:first-child {
        border-radius: 0 0 0 18Px;
      }
    }
  }
  .MetronomeBox {
    width: 100%;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    z-index: 2;
  }
  .headTools {
    position: absolute;
    right: 20Px;
    top: 18Px;
    & > img {
      margin-left: 18Px;
      width: 24Px;
      height: 24Px;
      cursor: pointer;
    }
  }
  .beatWrap {
    margin-top: 30Px;
    width: 252Px;
    height: 252Px;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    .dot {
      position: absolute;
      width: 24Px;
      height: 24Px;
      background: url('./imgs/dot.png') no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
      z-index: 3;
    }
    .round {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      border-radius: 50%;
      border: 10Px solid #d1d1d1;
      z-index: 1;
    }
    .mycanvas {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 2;
    }
    .beatCon {
      border-radius: 50%;
      z-index: 4;
      width: 200Px;
      height: 200Px;
      background: url('./imgs/yuan.png') no-repeat;
      background-size: 100% 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      .optMid {
        margin: 5Px 0;
        display: flex;
        align-items: center;
        :deep(.n-input-number) {
          width: 74Px;
          height: 52Px;
          margin-left: 4Px;
          .n-input {
            height: 100%;
            --n-height: 100% !important;
            --n-color-focus: initial !important;
            --n-color: initial !important;
            --n-padding-left: initial !important;
            --n-padding-right: initial !important;
            --n-color-disabled: initial !important;
            --n-caret-color: #3a3939 !important;
            .n-input__border,
            .n-input__state-border {
              display: none;
            }
            .n-input__input-el {
              text-align: center;
              font-family: DINA !important;
              font-weight: bold !important;
              font-size: 45Px !important;
              color: #000000 !important;
            }
            &.n-input--disabled {
              cursor: initial;
              .n-input__input-el {
                cursor: initial;
              }
            }
          }
        }
      }
      .optImg {
        cursor: pointer;
        width: 35Px;
        height: 35Px;
      }
    }
  }
  .selectCon {
    display: flex;
    margin-top: 22Px;
    :deep(.n-select) {
      width: 130Px;
      .n-base-selection--selected {
        --n-height: 48Px !important;
        --n-border-radius: 24Px !important;
        .n-base-selection__border,
        .n-base-selection__state-border {
          display: none;
        }
        .n-base-selection-input {
          padding: 0;
          .n-base-selection-input__content {
            .beatName {
              display: flex;
              justify-content: center;
              align-items: center;
              padding-top: 2Px;
              & > div:first-child {
                font-weight: 500;
                font-size: 30Px;
                color: #333333;
              }
              & > div:last-child {
                margin-left: 2Px;
                font-weight: 500;
                font-size: 14Px;
                color: #333333;
                margin-top: 4Px;
              }
            }
          }
        }
      }
    }
    :deep(.beatSymbolSel.n-select) {
      margin-left: 15Px;
      .n-base-selection-input__content {
        display: flex;
        justify-content: center;
        .beatSymbolImg {
          width: 44Px;
          height: 46Px;
          &.beatSymbolImg1 {
            background: url('./imgs/b1.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg2 {
            background: url('./imgs/b2.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg3 {
            background: url('./imgs/b3.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg4 {
            background: url('./imgs/b4.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg5 {
            background: url('./imgs/b5.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg6 {
            background: url('./imgs/b6.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg7 {
            background: url('./imgs/b7.png') no-repeat;
            background-size: 100% 100%;
          }
        }
      }
    }
  }
  .sliderList {
    margin-top: 24Px;
    display: flex;
    align-items: center;
    & > img {
      width: 18Px;
      height: 18Px;
      margin-right: 16Px;
    }
    .sliderText {
      width: 32Px;
      font-weight: 500;
      font-size: 16Px;
      color: #1cacf1;
      margin-left: 16Px;
    }
    :deep(.n-slider-rail) {
      height: 6Px;
      line-height: 6Px;
      background: #ffffff;
      border-radius: 4Px;
      width: 194Px;
      .n-slider-rail__fill {
        background: linear-gradient(90deg, #63daff 0%, #1798ff 100%);
        border-radius: 4Px;
      }
    }
    .thumbDot {
      width: 21Px;
      height: 21Px;
    }
  }
  .playBtn {
    cursor: pointer;
    margin-top: 20Px;
    width: 272Px;
    height: 54Px;
    background: #00acff;
    border-radius: 27Px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-weight: 600;
    font-size: 18Px;
    color: #ffffff;
    & > img {
      margin-left: 14Px;
      width: 13Px;
      height: 14Px;
      &.pauseImg {
        width: 12Px;
        height: 13Px;
      }
    }
  }
}
</style>
<style lang="less">
.n-base-select-menu.n-select-menu {
  .beatValOptItem {
    padding: 0 9Px !important;
    display: flex;
    justify-content: center;
    &.n-base-select-option::before {
      transition: initial;
    }
    &.n-base-select-option--selected {
      .n-base-select-option__content {
        color: #47a7fe;
      }
    }
    &.n-base-select-option--pending {
      .n-base-select-option__content {
        color: #ffffff;
      }
      &::before {
        background: #47a7fe !important;
        border-radius: 6Px !important;
        left: 9Px;
        right: 9Px;
      }
    }
    .n-base-select-option__content {
      font-weight: 500;
      font-size: 18Px;
      color: #777777;
    }
  }
  .beatSymbolOptItem {
    display: flex;
    justify-content: center;
    &.n-base-select-option::before {
      transition: initial;
    }
    &.n-base-select-option--selected {
      .n-base-select-option__content {
        .beatSymbolImg {
          &.beatSymbolImg1 {
            background: url('./imgs/a1.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg2 {
            background: url('./imgs/a2.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg3 {
            background: url('./imgs/a3.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg4 {
            background: url('./imgs/a4.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg5 {
            background: url('./imgs/a5.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg6 {
            background: url('./imgs/a6.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg7 {
            background: url('./imgs/a7.png') no-repeat;
            background-size: 100% 100%;
          }
        }
      }
    }
    &.n-base-select-option--pending {
      .n-base-select-option__content {
        .beatSymbolImg {
          &.beatSymbolImg1 {
            background: url('./imgs/c1.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg2 {
            background: url('./imgs/c2.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg3 {
            background: url('./imgs/c3.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg4 {
            background: url('./imgs/c4.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg5 {
            background: url('./imgs/c5.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg6 {
            background: url('./imgs/c6.png') no-repeat;
            background-size: 100% 100%;
          }
          &.beatSymbolImg7 {
            background: url('./imgs/c7.png') no-repeat;
            background-size: 100% 100%;
          }
        }
      }
      &::before {
        background: #47a7fe !important;
        border-radius: 6Px !important;
        left: 9Px;
        right: 9Px;
      }
    }
    .beatSymbolImg {
      width: 44Px;
      height: 46Px;
      &.beatSymbolImg1 {
        background: url('./imgs/b1.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg2 {
        background: url('./imgs/b2.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg3 {
        background: url('./imgs/b3.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg4 {
        background: url('./imgs/b4.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg5 {
        background: url('./imgs/b5.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg6 {
        background: url('./imgs/b6.png') no-repeat;
        background-size: 100% 100%;
      }
      &.beatSymbolImg7 {
        background: url('./imgs/b7.png') no-repeat;
        background-size: 100% 100%;
      }
    }
  }
}
.metronomeConBoxClass_drag
  .v-binder-follower-container
  .n-base-select-menu.n-select-menu {
  --n-border-radius: 10Px !important;
  .n-scrollbar-rail.n-scrollbar-rail--vertical {
    right: 3Px;
    --n-scrollbar-width: 3Px !important;
    opacity: 0.4;
  }
}
</style>
