<template>
  <view
    class="kip-notice-bar"
    :style="{ backgroundColor: modeConfig.bgColor, height: '30px' }"
  >
    <slot name="left-icon" class="kip-notice-bar-left-icon">
      <k-icon
        :name="modeConfig.icon"
        class="kip-notice-bar-left-icon"
        :size="16"
        :color="modeConfig.iconColor"
      />
    </slot>
    <view class="kip-notice-bar-wrap">
      <view
        class="kip-notice-bar-content"
        ref="box"
        v-if="textList.length"
        :animation="animationData"
      >
        <view
          class="kip-notice-bar-item"
          v-for="(bar, index) in textList"
          :key="index"
          ref="list"
          :style="{ marginRight: `${spacing}px` }"
          @click="(e) => onClick(e, bar, index)"
        >
          <view
            class="kip-notice-bar-pre-text"
            ref="preText"
            :style="{ color: preColor }"
            >{{ bar.preText }}</view
          >
          <view class="kip-notice-bar-text">{{ bar.text }}</view>
        </view>
      </view>
      <view
        class="kip-notice-bar-content"
        ref="box"
        v-else
        :animation="animationData"
      >
        <view
          class="kip-notice-bar-item"
          ref="list"
          v-if="scrollable"
          @click="(e) => onClick(e, text, 0)"
        >
          <view
            class="kip-notice-bar-text"
            :style="{
              color: color,
            }"
          >
            {{ text }}
          </view>
        </view>
        <view
          class="kip-notice-bar-item"
          ref="listStatic"
          v-else
          @click="(e) => onClick(e, text, 0)"
        >
          <view
            class="kip-notice-bar-text-static"
            :class="{ 'is-static': !scrollable }"
            :style="{
              color: color,
              width: flag ? `${boxLength}px` : 'auto',
            }"
          >
            {{ text }}
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import Vue, { VNode } from 'vue';
interface TextList {
  preText?: string;
  text: string;
  [key: string]: any;
}
export default Vue.extend({
  name: 'k-notice-bar',
  props: {
    textList: {
      type: Array,
      default: (): TextList[] => {
        return [];
      },
    },
    preColor: {
      type: String,
      default: '#333',
    },
    color: {
      type: String,
      default: '#333',
    },
    backgroundColor: {
      type: String,
      default: '',
    },
    leftIcon: {
      type: String,
      default: '',
    },
    delay: {
      type: Number,
      default: 2000,
    },
    scrollable: {
      type: Boolean,
      default: false,
    },
    spacing: {
      type: Number,
      default: 50,
    },
    baseTime: {
      type: Number,
      default: 10,
    },
    // office -> blue
    // public -> yellow
    mode: {
      type: String,
      default: 'office',
    },
    iconColor: {
      type: String,
      default: '',
    },
    text: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      animationData: {},
      animation: {} as UniApp.Animation,
      duration: 0,
      boxLength: 0,
      timer: {} as NodeJS.Timeout,
      firstPreWidth: 0 as number,
      flag: false as boolean,
    };
  },
  computed: {
    modeConfig() {
      if (this.mode === 'office') {
        return {
          icon: this.leftIcon || 'audio',
          bgColor: this.backgroundColor || '#f5f8fb',
          iconColor: this.iconColor || '#064C8A',
        };
      } else if (this.mode === 'public') {
        return {
          icon: this.leftIcon || 'audio',
          bgColor: this.backgroundColor || '#fefafa',
          iconColor: this.iconColor || '#D98750',
        };
      } else {
        return {
          icon: this.leftIcon || 'audio',
          bgColor: this.backgroundColor || '#f5f8fb',
          iconColor: this.iconColor || '#064C8A',
        };
      }
    },
  },
  mounted() {
    if (this.textList && this.textList.length) {
      this.play();
    }
    if (this.text) {
      this.play();
    }
  },
  watch: {
    textList: {
      handler(val) {
        if (val && val.length) {
          this.play();
        }
      },
      deep: true,
    },
    text: {
      handler(val) {
        if (val) {
          this.play();
        }
      },
    },
  },
  beforeDestroy: function () {
    this.animationData = {};
  },
  methods: {
    play() {
      this.getBoxLength();
      if (this.scrollable) {
        this.animation = uni.createAnimation();
        this.animationData = {};
        this.running(0, 0);
        this.timer = setTimeout(() => {
          this.collectTheLength('first');
        }, this.delay);
      }
    },
    onClick(event: TouchEvent, row: TextList | any, index: number) {
      this.$emit('click', event, row, index);
    },
    collectTheLength(str: string) {
      clearTimeout(this.timer);
      const query = uni.createSelectorQuery().in(this);
      let totalDistance: number;
      if (this.textList.length) {
        query
          .selectAll('.kip-notice-bar-item')
          .boundingClientRect((data) => {
            totalDistance = (data as any[]).reduce(
              (pre: any, item: any): number => {
                pre += item.width;
                return pre;
              },
              this.spacing
            );
            if (str === 'first') {
              this.duration = (totalDistance / this.baseTime) * 100;
            } else if (str === 'again') {
              this.duration =
                ((totalDistance < this.boxLength
                  ? this.boxLength
                  : totalDistance) /
                  this.baseTime) *
                100;
            }
            this.running(-totalDistance, this.duration);
            this.timer = setTimeout(() => {
              if (this.timer) {
                clearTimeout(this.timer);
              }
              this.running(this.boxLength, 0);
              setTimeout(() => {
                this.collectTheLength('again');
              }, 50);
            }, this.duration);
          })
          .exec();
      } else {
        query
          .select('.kip-notice-bar-item')
          .boundingClientRect((data) => {
            totalDistance = data.width as number;
            if (str === 'first') {
              this.duration = (totalDistance / this.baseTime) * 100;
            } else if (str === 'again') {
              this.duration =
                ((totalDistance < this.boxLength
                  ? this.boxLength
                  : totalDistance) /
                  this.baseTime) *
                100;
            }
            this.running(-totalDistance, this.duration);

            this.timer = setTimeout(() => {
              if (this.timer) {
                clearTimeout(this.timer);
              }
              this.running(this.boxLength, 0);
              setTimeout(() => {
                this.collectTheLength('again');
              }, 50);
            }, this.duration);
          })
          .exec();
      }
    },
    getBoxLength() {
      const query = uni.createSelectorQuery().in(this);
      query
        .select('.kip-notice-bar-content')
        .boundingClientRect((data) => {
          this.boxLength = data.width as number;
          this.$nextTick(() => {
            this.flag = true;
          });
        })
        .exec();
    },
    running(distance: number, duration: number) {
      this.animation.translateX(distance).step({ duration });
      this.animationData = this.animation.export();
    },
  },
});
</script>
<style scoped lang="scss">
.kip-notice-bar {
  width: 100%;
  max-width: 100vw;
  border-radius: 30px;
  padding: 0 9px;
  box-sizing: border-box;
  display: flex;
  align-items: center;

  .kip-notice-bar-left-icon {
    margin-right: 10px;
    margin-left: 5px;
  }

  .kip-notice-bar-wrap {
    min-width: calc(100% - 28px);
    font-size: 12px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;

    &::-webkit-scrollbar {
      width: 0;
    }

    .kip-notice-bar-content {
      min-width: 100%;
      display: flex;

      .kip-notice-bar-item {
        white-space: nowrap;
        display: flex;
        align-items: center;

        .kip-notice-bar-text-static {
          &.is-static {
            text-overflow: ellipsis;
            overflow: hidden;
            white-space: nowrap;
          }
        }
      }
    }

    .kip-notice-bar-pre-text {
      font-weight: 600;
    }
  }
}
</style>
