<template>
    <view class="canvas-box">
      <canvas :style="'width:'+canvas_width+'px;height:'+canvas_height+'px;'" canvas-id="poster-canvas"></canvas>
    </view>
</template>

<script>
import { getQrcode,getImgBase64 } from '../../common/api'
import { imageToBase64,base64ToImage } from '../../common/utils'
export default {
  name: 'yt-canvas',
   props: {
    rect: {
      type: Object
    }
  },
  data() {
    return {
      canvas_context: null,
      result_path:null,
      canvas_width:750,
      canvas_height:2000,
      resolve:null,
      reject:null
    }
  },
  created () {
    if(this.rect){
      let {width,height} = this.rect;
      this.canvas_width = width;
      this.canvas_height = height;
    }
  },
  methods: {
    // 父页面直接通过refs调用init方法传参并生成海报
    async init({ bgImg,width,height,steps,qrcodePath,userinfo },autoSave = true) {
      // #ifndef MP-TOUTIAO
      this.canvas_width = width
      this.canvas_height = height
      // #endif
      if(!userinfo){
        userinfo = {
          avatarUrl:'https://ttmini.yizhiwechat.com/yzInterstTest/fission/default-avatar.png',
          nickName:'匿名用户'
        }
      }
      
      let ctx = null
      if(this.canvas_context){
        ctx = this.canvas_context
      }else{
        ctx = uni.createCanvasContext('poster-canvas', this);
        this.canvas_context = ctx
      }
      if(autoSave){
        this.$yt.loading('正在保存中','sandglass',this)
      }
      
      // 填充背景色
      ctx.save()
      ctx.setFillStyle('white');// 填充白色
      ctx.fillRect(0, 0, width , height * 10);// 画出矩形白色背景
      ctx.restore()
      // 如果设置有背景图 ，绘制背景图
      if(bgImg){
        await uni.getImageInfo({
          src: bgImg
        })
        .then(async img => {
          img = img[0] || img[1];
          if (img.errMsg === 'getImageInfo:ok') {
            // #ifdef MP-TOUTIAO
            if(img.path){
              img.path = 'data:image/jpg;base64,' + await imageToBase64(img.path)
            }
            // #endif
            ctx.drawImage(img.path, 0, 0, img.width, img.height);
          }
        });
      }

      // 文字段落绘制
      function findBreakPoint(text, width, context) {
        var min = 0;
        var max = text.length - 1;

        while (min <= max) {
          var middle = Math.floor((min + max) / 2);
          var middleWidth = context.measureText(text.substr(0, middle)).width;
          var oneCharWiderThanMiddleWidth = context.measureText(
            text.substr(0, middle + 1)
          ).width;
          if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
            return middle;
          }
          if (middleWidth < width) {
            min = middle + 1;
          } else {
            max = middle - 1;
          }
        }
        return -1;
      }
      function breakLinesForCanvas(text, width) {
        const _result = [];
        let breakPoint = 0;
        while ((breakPoint = findBreakPoint(text, width, ctx)) !== -1) {
          _result.push(text.substr(0, breakPoint));
          text = text.substr(breakPoint);
        }
        if (text) {
          _result.push(text);
        }
        return _result;
      }

      
      for(let index = 0,steps_length = steps.length; index < steps_length; index++){
        const item = steps[index];
        
        switch(item.type){
          case 'image':{
            let image = {}
            if(/^http/.test(item.context)){
              await uni.getImageInfo({
                src: item.context
              })
              .then(img => {
                img = img[0] || img[1];
                if (img.errMsg === 'getImageInfo:ok') {
                  image = img
                }
              })
              // #ifdef MP-TOUTIAO
              if(image.path){
                image.path = 'data:image/jpg;base64,' + await imageToBase64(image.path)
              }
              // #endif
            }else if(/^(\{\{)\s*(qrcode)\s*(\}\})$/.test(item.context)){
              // 绘制二维码 未处理base64转零时路径，头条系以外环境不支持
              let {tid,mid} = this.$store.state.index;
              // #ifdef MP-WEIXIN
              const UrlParam = function(url) {
                let params = {},h;
                let [path,hash] = url.split('?')
                hash = hash.split('&');
                for (var i = 0; i < hash.length; i++) {
                  h = hash[i].split("=");
                  params[h[0]] = h[1];
                }
                return Object.assign(params,{path});
              }
              const {path,agent_id,spread_id,product_id} = UrlParam(qrcodePath)
              qrcodePath = `${path}?a=${agent_id}_${spread_id}&product_id=${product_id}`
              // #endif
              const qrParams = { tid,path:qrcodePath };
              
              mid && (qrParams['mid'] = mid);
              const qrcode_base64 = await getQrcode(qrParams).catch(function(){})
              if(qrcode_base64 && typeof(qrcode_base64)==='string'){
                // #ifdef MP-TOUTIAO
                image.path = 'data:image/jpg;base64,' + qrcode_base64
                // #endif
                // #ifndef MP-TOUTIAO
                image.path = await base64ToImage(qrcode_base64)
                // #endif
              }else{
                break
              }
            }else if(/^(\{\{)\s*(avatar)\s*(\}\})$/.test(item.context)){
              // 绘制抖音用户头像
              // https://ttmini.yizhiwechat.com/yzInterstTest/fission/default-avatar.png 默认用户头像
              if(userinfo.avatarUrl){
                // 通过后台接口把图片转base64
                const { img_base64,img_base64_head } = await getImgBase64({ url:userinfo.avatarUrl })
                // #ifdef MP-TOUTIAO
                image.path = img_base64_head + img_base64
                // #endif
                // #ifndef MP-TOUTIAO
                image.path = await base64ToImage(img_base64)
                // #endif
              }
              if(!image.path){
                await uni.getImageInfo({
                  src: 'https://ttmini.yizhiwechat.com/yzInterstTest/fission/default-avatar.png'
                })
                .then(img => {
                  img = img[0] || img[1];
                  if (img.errMsg === 'getImageInfo:ok') {
                    image = img
                  }
                })
                // #ifdef MP-TOUTIAO
                if(image.path){
                  image.path = 'data:image/jpg;base64,' + await imageToBase64(image.path)
                }
                // #endif
              }
            }else{
              image.path = item.context
            }
            if(image.path){
              // eslint-disable-next-line prefer-const
              let { x, y, style:{ w, h,width:imageWidth, height:imageHeight,arc }} = item
              w = /\d+/.test(w||imageWidth) ? (w||imageWidth) : image.width;
              h = /\d+/.test(h||imageHeight) ? (h||imageHeight) : image.height;
              
              if(arc){
                ctx.save();
                ctx.beginPath();
                // ctx.setLineWidth(0)
                // ctx.setStrokeStyle("#ffffff");
                ctx.arc(x + w / 2,y + h / 2,w / 2,0,Math.PI * 2,false);
                ctx.clip();
                ctx.drawImage(image.path, x, y, w, h);
                ctx.restore();
                ctx.closePath();
                // ctx.stroke();
              }else{
                ctx.drawImage(image.path, x, y, w, h);
              }
            }
            break;
          }
          case 'text':{
            const { color, align, base, font,stroke } = item.style
            ctx.beginPath();
            ctx.font = (font || '32px') + ' Arial';
            ctx.setFillStyle(color || '#000000');
            ctx.setTextAlign(align || 'left');
            ctx.setTextBaseline(base || 'middle');
            
            if(/^(\{\{)\s*(nickname)\s*(\}\})$/.test(item.context)){
              ctx.fillText(userinfo.nickName,item.x,item.y)
            }else{
              ctx.fillText(item.context,item.x,item.y)
            }
            // #ifndef MP-TOUTIAO 
            if(stroke){
              ctx.setStrokeStyle(stroke)
              if(/^(\{\{)\s*(nickname)\s*(\}\})$/.test(item.context)){
              ctx.strokeText(userinfo.nickName,item.x,item.y)
              }else{
                ctx.strokeText(item.context,item.x,item.y)
              }
            }
            // #endif
            ctx.stroke();
            break;
          }
          case 'longtext':{
            const { color, align, base, font,autoHeight } = item.style; const text_width = item.style.width;

            const lineHeight = parseInt((font || '32px').match(/\d+/)[0] * 1.3);
            ctx.beginPath();
            ctx.font = (font || '32px') + ' Arial';
            ctx.setFillStyle(color || '#ffffff');
            ctx.setTextAlign(align || 'left');
            ctx.setTextBaseline(base || 'middle');
            let lineLength = 0;
            let pLength = 0
            const content_data = item.context.split(/[\n|\r]+/g);
            content_data.forEach(function(paragraph,index){
              pLength = 15 * index;
              const result = breakLinesForCanvas(paragraph, text_width);// 参数(段落文本,文本宽度)
              result.forEach(function(line, idx) {
                ctx.fillText(line, item.x, (lineLength++) * lineHeight + item.y + pLength); // 参数(text,left,top)
              });
            })
            ctx.stroke();
            if(autoHeight){
              height += (lineLength * lineHeight + pLength)
            }
            break;
          }
          case 'path':{
            const paths = JSON.parse(item.context)
            let color = item.style.color || '#ffffff';
            let grd = null
            if(/^\[(.+)\]$/.test(color)){
              color = JSON.parse(color)
              const gradient_direction = item.style.gradient_direction ? JSON.parse(item.style.gradient_direction) : [...paths[0],...paths[1]];
              
              grd = ctx.createLinearGradient(...gradient_direction)
              for (let index = 0; index < color.length; index++) {
                const element = color[index];
                grd.addColorStop(...element)
              }
            }
            ctx.beginPath();
            ctx.setLineWidth(1);
            ctx.setStrokeStyle(grd || color)
            // ctx.setLineDash([6, 4]);
            paths.forEach((v,i) => {
              if(i){
                ctx.lineTo(...v);
              }else{
                ctx.moveTo(...v);
              }
            })
            ctx.closePath();
            if(item.style.fill){
              ctx.setFillStyle(grd || color);
              ctx.fill();
            }else{
              ctx.stroke();
            }
            
            break;
          }
        }
      }
      // ctx.draw(true)
      return this.resultDraw(ctx,width,height).then(result_path => {
        if(autoSave){
          this.$yt.messageClose(this)
        }
        if(result_path && autoSave){
          this.savePhoto(result_path)
        }else if(autoSave){

          uni.showToast({
            title: '生成失败,无法保存!',
            duration: 2000,
            icon: 'none'
          });
        }
        return result_path
      }).catch(() => {
        this.$yt.messageClose(this)
        uni.hideLoading();
        return "绘制或者保存失败"
      })
    },
    savePhoto(result_path){
      let scope = 'scope.album'
      // #ifndef MP-TOUTIAO
      scope = 'scope.writePhotosAlbum'
      // #endif
      this.auth(scope).then(() => {
        uni.saveImageToPhotosAlbum({
          filePath: result_path || this.result_path,
          success() {
            uni.showToast({
              title: '保存成功',
              duration: 2000
            });
          },
          fail() {
            uni.showToast({
              title: '保存失败',
              duration: 2000,
              icon: 'none'
            });
          }
        });
      })
    },
    resultDraw(ctx,width,height){
      return new Promise((resolve,reject) => {
        ctx.draw(true,() => {
          uni.canvasToTempFilePath({
            x: 0,
            y: 0,
            width: width,
            height: height,
            canvasId: 'poster-canvas',
            fileType: 'jpg',
            quality: 0.8,
            success: res => {
              if(res.tempFilePath){
                this.result_path = res.tempFilePath
                this.$emit('callback',res.tempFilePath)
              }
              resolve(res.tempFilePath)
            },
            fail(e){
              setTimeout(() => {
                reject(e)
              },300)
            }
          },this);
        });
      })
    },
    auth(scope) {
      const failCall = function(){
        uni.showModal({
          title: '提示',
          content: '保存图片需要开启相册权限!',
          showCancel:false,
          success: function() {
            uni.openSetting()
          }
        });
      }
      return new Promise((resolve,reject) => {
        uni.getSetting({
          success: (auth) => {
            if (!auth.authSetting[scope]){
              uni.authorize({
                scope: scope,
                success: (ret) => {
                  resolve(true)
                },
                fail(e) {
                  if(scope !== 'scope.userInfo'){
                   failCall()
                  }
                  reject('授权失败,打开设置页!')
                }
              });
            }else{
              resolve(true)
            }
          },
          fail:e => {
            if(scope !== 'scope.userInfo'){
              failCall()
            }
            reject('授权失败,打开设置页!')
          }
        });
      })
    }
  }
};
</script>

<style lang="scss" scoped>
.canvas-box{
  width:0px;
  height:0px;
  overflow:hidden;
  position: relative;
  canvas{
    position: absolute;
    left: -10000px;
    top: 0;
  }
}
</style>
