<template>
  <div v-if="fontReady">
    <v-stage :config="content" v-if="content" @mousedown="handleStageMouseDown">
      <v-layer>
        <v-rect v-if="content.background.type === 'color'" :config="content.background">
        </v-rect>
        <v-image v-if="content.background.type === 'image' && imageBgConfig" :config="imageBgConfig"></v-image>
      </v-layer>
      <v-layer>
        <template v-for="(item, key) in content.blocks">
          <v-text v-if="item.type === 'text'" :config="item"
                  @dragmove="onMove($event, item)"
                  @mousedown="handleStageMouseDown($event, item)"
                  @transform="handleTransformEnd"
                  @transformend="handleTransformEnd"></v-text>
          <v-image v-else-if="item.type === 'image'" :config="item"
                   @dragmove="onMove($event, item)"
                   @mousedown="handleStageMouseDown($event, item)"
                   @transform="handleTransformEnd"
                   @transformend="handleTransformEnd"></v-image>
          <v-image v-else-if="item.type === 'qrcode'" :config="item"
                   @dragmove="onMove($event, item)"
                   @mousedown="handleStageMouseDown($event, item)"
                   @transform="handleTransformEnd"
                   @transformend="handleTransformEnd"></v-image>

        </template>

        <v-transformer ref="transformer"/>
      </v-layer>
    </v-stage>
  </div>
  <div v-else>资源加载中...</div>
</template>

<script setup>
import {fonts} from "@/views/shop/templateInfo/drawCanvas";
import QRCode from 'qrcode'

const props = defineProps({content: Object, selectBlock: Object,})
const emit = defineEmits([
  'update:select-block'
])
const {content, selectBlock} = toRefs(props)
const imageBgConfig = ref(null);
const transformer = ref(null);
const fontReady = ref(false)

function loadFont() {
  let promiseFonts = fonts.map(({name, value}) => {
    const font = new FontFace(name, `url(${value})`);
    document.fonts.add(font)
    return font.load()
  })

  Promise.all(promiseFonts).then(() => {
    fontReady.value = true
    nextTick(initDraw)
  })
}

loadFont();

function initDraw() {
  const node = transformer.value.getNode()
  node.rotateEnabled(false)
  // node.resizeEnabled(false)
  node.anchorFill('#FFFFFF00');
  node.anchorStroke('#777777CC');
  node.anchorStrokeWidth(1);
  node.borderStroke('#777777CC');
  node.borderStrokeWidth(1);
}

function onMove({target}, item) {
  let {x, y} = target.attrs
  item.x = Math.round(x || 0)
  item.y = Math.round(y || 0)
}

function handleTransformEnd(e) {
  const attr = e.target.attrs
  const block = selectBlock.value;
  block.scaleX = 0
  block.scaleY = 0
  const {width, height, scaleX, scaleY, rotation} = attr
  const {textWidth, textHeight} = e.target

  nextTick(() => {
    block.width = Math.round((width || textWidth) * scaleX)
    block.height = Math.round((height || textHeight) * scaleY)
    block.rotation = rotation
    block.scaleX = 1
    block.scaleY = 1
  })
}

function handleStageMouseDown(e, item) {
  const clickedOnTransformer =
      e.target.getParent().className === 'Transformer'
  if (clickedOnTransformer) {
    return;
  }
  handleBlockSelect(item)
}

function handleBlockSelect(item) {
  if (item == null) {
    emit('update:select-block', null)
    updateTransformer(-1)
    return;
  }
  nextTick(() => {
    emit('update:select-block', item)
    updateTransformer(item.index)
  })
}

watch(selectBlock, (newValue, oldValue) => {
  nextTick(() => {
    if (newValue != null) {
      updateTransformer(newValue.index)
    } else {
      updateTransformer(-1)
    }
  })
})

function updateTransformer(index) {
  const transformerNode = transformer.value.getNode();
  const stage = transformerNode.getStage();
  const selectedNode = stage.findOne(node => node.attrs.index === index);
  if (selectedNode === transformerNode.node()) {
    return;
  }
  if (selectedNode) {
    transformerNode.nodes([selectedNode]);
  } else {
    transformerNode.nodes([]);
  }
}

watchEffect(() => {
  let background = content.value.background
  if (background && background.type === 'image' && background.src != null) {
    console.log(background)
    buildImage(background)
  }
})

watchEffect(() => {
  let blocks = content.value.blocks
  if (!blocks) {
    return
  }
  blocks.forEach(block => {
    if (block.type === 'image') {
      const image = new Image()
      block.image = image
      image.src = block.src
    }else if (block.type === 'qrcode'){
      QRCode.toDataURL(block.text, {width: block.width, height: block.height}).then(src=> {
        const image = new Image()
        block.image = image
        image.src = src
      })
    }
  })
})

function buildImage(background) {
  if (imageBgConfig.value !== background) {
    imageBgConfig.value = Object.assign({}, background)
  }
  const image = new Image()
  image.src = background.src
  image.onload = () => {
    imageBgConfig.value.image = image
  }
}

function onEnd({target}, item) {
  let {width, height} = content.value
  let {x, y, padding} = target.attrs

  width -= (target.textWidth + padding)
  height -= (target.textHeight + padding)

  if (x < 0) {
    x = 0
  }
  if (x > width) {
    x = width
  }
  if (y < 0) {
    y = 0
  }
  if (y > height) {
    y = height
  }

  item.x = x
  item.y = y
}

defineExpose({
  handleBlockSelect,
  imageBgConfig,
})
</script>

<style scoped>

</style>