<template>
  <div
    ref="downloadButtonRef"
    class="download-button"
    :style="{ width: buttonWidth + 'px', height: buttonHeight + 'px', borderRadius: borderRadius + 'px' }"
    :class="[state]"
  >
    <button class="button" :disabled="state === 'downloading'" :style="{ borderRadius: borderRadius + 'px' }">
      <div class="circle">
        <el-icon :class="{ 'is-loading': state === 'downloading' }" :size="state === 'downloading' ? 16 : 20" color="#ffffff">
          <solar-round-arrow-down-outline v-if="state === 'init'"></solar-round-arrow-down-outline>
          <icon-loading v-else-if="state === 'downloading'"></icon-loading>
          <solar-check-circle-linear v-else-if="state === 'succeed'"></solar-check-circle-linear>
          <solar-confounded-circle-linear v-else-if="state === 'error'"></solar-confounded-circle-linear>
        </el-icon>
      </div>
      <div class="title-box">
        <p v-if="state === 'init'" class="title">立即更新</p>
        <p v-else-if="state === 'downloading'" class="title">下载中</p>
        <p v-else-if="state === 'succeed'" class="title">立即安装</p>
        <p v-else-if="state === 'error'" class="title">重新安装</p>
      </div>
    </button>
    <svg class="border" :style="{ borderRadius: borderRadius + 'px' }" :viewBox="`0 0 ${buttonWidth} ${buttonHeight}`">
      <rect class="progress-track" x="0" y="0" :width="buttonWidth" :height="buttonHeight" :rx="borderRadius" :ry="borderRadius"></rect>
      <rect
        class="progress-bar"
        x="0"
        y="0"
        :width="buttonWidth"
        :height="buttonHeight"
        :rx="borderRadius"
        :ry="borderRadius"
        :stroke-dasharray="circumference"
        :stroke-dashoffset="progressOffset"
      ></rect>
    </svg>
  </div>
</template>

<script setup lang="ts">
  import SolarCheckCircleLinear from '~icons/solar/check-circle-linear';
  import SolarRoundArrowDownOutline from '~icons/solar/round-arrow-down-outline';
  import SolarConfoundedCircleLinear from '~icons/solar/confounded-circle-linear';
  import { Loading as IconLoading } from '@element-plus/icons-vue';
  import { useElementSize } from '@vueuse/core';

  interface Props {
    /** 进度 */
    progress?: number;
    /** 状态 */
    state?: 'downloading' | 'error' | 'init' | 'succeed';

    /** 按钮高度 */
    buttonHeight?: number;
    /** 圆角 */
    borderRadius?: number;
  }

  const props = withDefaults(defineProps<Props>(), {
    progress: 0,
    state: 'init',
    buttonHeight: 40,
    borderRadius: 20,
  });

  const downloadButtonRef = useTemplateRef('downloadButtonRef');
  const { width: buttonWidth } = useElementSize(downloadButtonRef);

  // 计算周长
  const circumference = computed(() => 2 * (buttonWidth.value + props.buttonHeight));

  // 修复进度条偏移量计算
  const progressOffset = computed(() => circumference.value - (props.progress / 100) * circumference.value);
</script>

<style lang="scss" scoped>
  .download-button {
    position: relative;

    .button {
      position: absolute;
      top: 0;
      left: 0;
      box-sizing: content-box;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: calc(100%);
      padding: 0;
      margin: 0;
      overflow: hidden;
      cursor: pointer;
      background: none;
      background-color: var(--el-color-primary);
      transition: all 0.3s linear;

      &:disabled {
        cursor: not-allowed;
        opacity: 0.7;
      }

      .circle {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        transition: all var(--animation-time) linear;
      }

      .title-box {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        margin-left: 6px;
        overflow: hidden;
        white-space: nowrap;

        .title {
          padding-right: 8px;
          font-size: 14px;
          color: #ffffff;
          text-align: center;
          overflow-wrap: break-word;
        }
      }
    }

    .border {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 3;
      box-sizing: border-box;
      width: 100%;
      height: 100%;

      .progress-track {
        fill: rgba(0, 0, 0, 0);
        stroke: #409eff;
        stroke-width: 4px;
      }

      .progress-bar {
        fill: rgba(0, 0, 0, 0);
        stroke: #67c23a;
        stroke-linecap: round;
        stroke-width: 4px;
        transition: stroke-dashoffset 0.3s ease-out;
      }
    }

    &.init {
      .button {
        background-color: var(--el-color-primary);
        transition: all 0s linear;
      }

      .border .progress-bar {
        transition: stroke-dashoffset 0s ease-out;
      }
    }

    &.succeed {
      .button {
        background-color: var(--el-color-success);
      }

      .border .progress-track {
        stroke: #67c23a;
      }
    }

    &.error {
      .button {
        background-color: var(--el-color-error);
      }

      .border .progress-track {
        stroke: #f56c6c;
      }
    }

    &.downloading .button {
      background-color: var(--el-color-primary);
    }
  }
</style>
