<template>
  <div :class='["TimeLine1", { "auto-size": autoSize }]' ref="TimeLine1Ref">
    <!-- 节点 -->
    <div class="node" v-for="(item, index) in data" ref="nodeRefs">
      <span class="top-label">
        <slot name="bottom-label" :data="item">
          {{ item.time }}
        </slot>
      </span>
      <div class="center">
        <div class="line" v-if="!index" :style="{ width: `${nodeLinesWidth[-1]}px` }" />
        <div class="circle" :style="{ '--active-color': !item.isActive ? normalColor : activeColor }"></div>
        <div class="line" :style="{
          width: `${nodeLinesWidth[index]}px`,
          borderImage: getBorderImageStyle(item),
        }" />
      </div>
      <slot name="bottom-label" :data="item">
        <div class="bottom"
          :style="{ backgroundImage: `url(${require(`./images/bg${item.isActive ? '-active' : ''}.svg`)})` }">
          {{ item.label }}
        </div>
      </slot>
    </div>

  </div>
</template>

<script>

function getPositionAtCenter(element) {
  const { top, left } = element.getBoundingClientRect();

  return {
    x: left,
    y: top
  };
}

function getDistanceBetweenElements(domA, domB) {
  const domAPosition = getPositionAtCenter(domA);
  const domBPosition = getPositionAtCenter(domB);

  return Math.hypot(domAPosition.x - domBPosition.x, domAPosition.y - domBPosition.y);
}

export default {
  name: 'TimeLine1',
  props: {
    data: {
      type: Array,
      default: () => Array.from({ length: 15 }).map(() => ({
        time: "16.36",
        label: "阿发",
        isActive: false
      }))
    },
    activeColor: {
      type: String,
      default: "#39D5BF"
    },
    normalColor: {
      type: String,
      default: "#ccc"
    },
    lineActiveColor: {
      type: String,
      default: "linear-gradient(90deg, rgba(59, 216, 188, 1), rgba(29, 171, 215, 1)}) 2 2"
    },
    lineNormalColor: {
      type: String,
      default: null
    },
    // 自动适配宽度
    autoSize: {
      type: Boolean,
      default: true
    },
    filterDistance: {
      type: Function,
      default: null
    }
  },
  data() {
    return {
      nodeLinesWidth: {}
    }
  },
  watch: {
    data: {
      handler(data) {
        let needFilter = false
        const nodeLinesWidth = [];

        const filterDistance = num => needFilter ? this.filterDistance(num) : num;

        const removeDistance = 20 + 4 * 2;

        function getDistance(index) {
          return filterDistance(getDistanceBetweenElements(
            this.$refs.nodeRefs[index].querySelector('.center'),
            this.$refs.nodeRefs[index + 1].querySelector('.center'))
          ) - removeDistance
        };

        function getSpecialDistance(index) {
          return filterDistance(getDistanceBetweenElements(
            this.$refs.nodeRefs[index].parentElement,
            this.$refs.nodeRefs[index].querySelector('.center'))
          ) - removeDistance
        }

        const getLineWidths = () => {
          nodeLinesWidth.length = 0;

          data.forEach((_, index) => {
            if (index === data.length - 1) {
              if (this.autoSize) {
                nodeLinesWidth[-1] = getSpecialDistance.call(this, 0)
                nodeLinesWidth[data.length - 1] = getSpecialDistance.call(this, data.length - 1)
              }

              return
            };

            nodeLinesWidth[index] = getDistance.call(this, index);
          });

          this.nodeLinesWidth = nodeLinesWidth;
        }

        this.$nextTick(() => {
          const timeLine1RefDom = this.$refs.TimeLine1Ref;
          if (timeLine1RefDom.clientWidth != timeLine1RefDom.getBoundingClientRect().width) {
            needFilter = true
          }
          getLineWidths();
        })
      },
      immediate: true
    }
  },
  mounted() {
    // console.log()
    console.log(this.$refs.nodeRefs[0].getBoundingClientRect())
  },
  methods: {
    getBorderImageStyle(item) {
      const linearColor = item.isActive ? (this.lineActiveColor || `${this.activeColor}, ${this.activeColor}`) : (this.lineNormalColor || `${this.normalColor}, ${this.normalColor}`)

      return `linear-gradient(90deg, ${linearColor}) 2 2`
    }
  }
}
</script>

<style lang='scss' scoped>
div.auto-size {
  justify-content: space-between;
  overflow: hidden;

  .node {
    flex: 1;
    min-width: auto !important;

    &:first-child,
    &:last-child {
      .line {
        width: auto;
      }
    }
  }
}

.TimeLine1 {
  color: #fff;
  width: auto;

  font-size: 14px;
  font-family: PingFang SC, PingFang SC;
  font-weight: 400;
  color: #FFFFFF;
  display: flex;
  flex-wrap: nowrap;
  overflow: auto;
  gap: 15px;
  padding-left: 15px;

  .node {
    display: flex;
    align-items: center;
    // justify-content: center;
    flex-direction: column;
    gap: 3px;
    min-width: 90px;

    .top-label {
      line-height: 16px;
      height: 24px;
    }

    .center {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      position: relative;

      .circle {
        border: 1px solid var(--active-color, #39D5BF);
        border-radius: 50%;
        width: 15px;
        height: 15px;
        position: relative;

        &::before {
          content: "";
          position: absolute;
          width: 72%;
          height: 72%;
          border-radius: 50%;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
          background-color: var(--active-color, #39D5BF);
        }
      }


      .line {
        position: absolute;
        height: 0px;
        opacity: 1;
        border: 2px solid;
        border-image: linear-gradient(90deg, rgba(59, 216, 188, 1), rgba(29, 171, 215, 1)) 2 2;

        &:first-child {
          right: calc(50% + 8px + 6px);
        }

        &:last-child {
          left: calc(50% + 8px + 6px);
        }
      }
    }

    &:first-child,
    &:last-child {
      .line {
        width: 60px;
      }
    }

    .bottom {
      line-height: 16px;
      background-repeat: no-repeat;
      background-size: 100% 100%;
      min-width: 90px;
      text-align: center;
      padding: 6px 12px;
      height: 27px;
    }
  }
}
</style>
