<template>
  <view class="scraping-happy" id="container">
    <canvas canvas-id="scraping-happy" class="scraping__canvas" :disable-scroll="true" @touchstart="touchstart"
      @touchmove="touchmove" @touchend="touchend" />
    <cover-view class="scraping__view">
      {{ showText }}
    </cover-view>
    <slot></slot>
  </view>
</template>

<script>
  /** @name 水印配置默认值 **/
  const WATERMARK = {
    text: '刮一刮',
    fontSize: 14,
    color: '#C5C5C5',
  }
  /** @name 标题配置默认值 **/
  const TITLE = {
    text: '刮一刮',
    fontSize: 16,
    color: '#333',
  }
  /** 
   * @name 涂层配置默认值 
   * @property { string } color 涂层颜色
   * @property { number } drawSize 清除涂层的画笔大小
   */
  const MASK = {
    color: '#DDDDDD',
    drawSize: 20,
  }
  /** @name 容错值，解决部分机型涂层没有覆盖满的情况，主要原因是由于像素尺寸不同导致的，应尽可能让width与height保持整数 **/
  const TOLERANT = 3;

  let ctx = null;

  export default {
    props: {
      /** @name 涂层设置 **/
      mask: {
        type: [String, Object],
      },
      /** @name 水印设置 **/
      watermark: {
        type: [String, Object],
      },
      /** @name 提示文字 **/
      title: {
        type: [String, Object],
      },
      /** @name 刮开百分之多少直接消除图层，为0的时候不消除 **/
      percentage: {
        type: Number,
        default: 40,
      },
      result: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        width: 0,
        height: 0,
        touchX: 0,
        touchY: 0,
        showText: ''
      }
    },
    computed: {
      maskSetting() {
        return {
          ...MASK,
          ...(typeof this.mask === 'object' ? this.mask : {
            text: this.mask
          }),
        }
      },
      watermarkSetting() {
        return {
          ...WATERMARK,
          ...(typeof this.watermark === 'object' ? this.watermark : {
            text: this.watermark
          }),
        };
      },
      titleSetting() {
        return {
          ...TITLE,
          ...(typeof this.title === 'object' ? this.title : {
            text: this.title
          }),
        };
      }
    },
    mounted() {
      // 获取画布实例
      ctx = uni.createCanvasContext('scraping-happy', this);
      this.init();
    },
    methods: {
      /** @name 初始化 **/
      init() {
        const query = uni.createSelectorQuery().in(this);
        query
          .select('#container')
          .boundingClientRect(({
            width,
            height
          }) => {
            this.width = width;
            this.height = height;
            setTimeout(() => {
              this.initCanvas();
              this.showText = this.result
            }, 20)
          })
          .exec();
      },
      /** @name 初始化canvas状态 **/
      initCanvas() {
        const {
          width,
          height
        } = this;
        // 清空矩形内容
        ctx.clearRect(0, 0, width, height);
        // 设置画笔颜色
        ctx.setFillStyle(this.maskSetting.color);
        // 绘制矩形
        ctx.fillRect(0, 0, width, height + TOLERANT);
        // 绘制水印
        this.drawWatermark();
        // 绘制提示文字
        this.drawTitle();
        // 绘制到canvas身上
        ctx.draw();
      },
      /** @name 绘制水印 **/
      drawWatermark() {
        if (!this.watermarkSetting.text) return;
        // 保存当前的绘图上下文
        ctx.save();
        // 旋转
        ctx.rotate((-10 * Math.PI) / 180);
        // 水印具体绘制过程
        const {
          width,
          height
        } = this;
        const watermarkWidth = this.watermarkSetting.text.length * this.watermarkSetting.fontSize;
        let x = 0;
        let y = 0;
        let i = 0;
        while ((x <= width * 5 || y <= height * 5) && i < 300) {
          ctx.setFillStyle(this.watermarkSetting.color);
          ctx.setFontSize(this.watermarkSetting.fontSize);
          ctx.fillText(this.watermarkSetting.text, x, y);
          x += watermarkWidth + watermarkWidth * 1.6;
          if (x > width && y <= height) {
            x = -Math.random() * 100;
            y += this.watermarkSetting.fontSize * 3;
          }
          i++;
        }
        ctx.restore();
      },
      /** @name 绘制提示文字 **/
      drawTitle() {
        if (!this.titleSetting.text) return;
        ctx.setTextAlign('center');
        ctx.setTextBaseline('middle');
        ctx.setFillStyle(this.titleSetting.color);
        ctx.setFontSize(this.titleSetting.fontSize);
        ctx.fillText(this.titleSetting.text, this.width / 2, this.height / 3);
      },
      /** @name 触摸事件 **/
      touchstart(e) {
        this.touchX = e.touches[0].x;
        this.touchY = e.touches[0].y;
      },
      async touchmove(e) {
        // 把画笔到画布中的指定点
        ctx.moveTo(this.touchX, this.touchY);
        // 清除涂层
        ctx.clearRect(this.touchX, this.touchY, this.maskSetting.drawSize, this.maskSetting.drawSize);
        ctx.draw(true);
        // 记录移动点位
        this.touchX = e.touches[0].x;
        this.touchY = e.touches[0].y;

        // if (this.percentage > 0) {
        //   const clearPercent = await this.getClearMaskPercent();
        // } 
      },
      async touchend() {
        if (this.percentage > 0) {
          const clearPercent = await this.getClearMaskPercent();
          if (clearPercent >= this.percentage) {
            ctx.moveTo(0, 0);
            ctx.clearRect(0, 0, this.width, this.height);
            ctx.stroke();
            ctx.draw(true);
            this.$emit('complete')
          }
        }
      },
      /** @name 计算被清除的涂层百分比 **/
      getClearMaskPercent() {
        return new Promise(resolve => {
          uni.canvasGetImageData({
            canvasId: 'scraping-happy',
            x: 0,
            y: 0,
            width: this.width,
            height: this.height,
            success: res => {
              // 区域内所有点的像素信息，它是一个数组，数组中每 "4" 项表示一个点的 rgba 值
              const allPointPixels = res.data;
              // 储存被清除的点-点的透明度
              const clearPoint = [];
              // 取透明度来判断，如果透明度值小于一半，则判断为该点已经被清除
              for (let i = 0; i < allPointPixels.length; i += 4) {
                if (allPointPixels[i + 3] < 128) {
                  clearPoint.push(allPointPixels[i + 3]);
                }
              }
              // 已被清除的百分比 = 清除的点 / 全部的点
              const percent = (
                (clearPoint.length / (allPointPixels.length / 4)) *
                100
              ).toFixed(2);
              resolve(percent);
            },
            fail: e => {
              console.log('canvasGetImageData', e);
            },
          }, this);
        });
      },
      /** @name 重置 **/
      reset() {
        this.initCanvas();
        this.touchX = 0;
        this.touchY = 0;
      }
    }
  };
</script>

<style>
  .scraping-happy {
    width: 100%;
    height: 200rpx;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .scraping__canvas {
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 10;
    /* background-color: red; */
    display: inline-block;
  }

  .scraping__view {
    position: absolute;
    z-index: 1;
    color: #f29100;
    font-size: 20px;
    font-weight: bold;
    letter-spacing: 8px;
  }
</style>