<script setup lang="ts">
import { Notify }                         from '@/platform';
import { copyrightMethod, processMethod } from '@/request/api';
import { useVisitor }                     from '@/stores';
import { useElementSize }                 from '@vueuse/core';
import { useRequest }                     from 'alova/client';
import p5                                 from 'p5';


const router = useRouter();
const Visitor = useVisitor();

const title = import.meta.env.SIX_APP_TITLE;
const { data: copyright } = useRequest(copyrightMethod);
const { send: handle, loading } = useRequest(processMethod, { immediate: false }).onSuccess(({ data }) => {
  if ( data ) {
    Visitor.$reset();
    router.push(data);
  } else {
    Notify.warning(`[路由] 配置异常无法解析正确路径，请联系管理员`);
  }
});

const container = useTemplateRef<HTMLDivElement>('container');
const { width, height } = useElementSize(container);

interface Bubble {
  text: string;
  color: string;
  x?: number;
  y?: number;
  dx?: number;
  dy?: number;
  diameter?: number;
}

watchEffect(() => {
  if ( width.value && height.value ) {
    init(
      { width: width.value, height: height.value * 0.90, container: container.value! });
  }
});

function init({ width, height, container }: { width: number; height: number; container: HTMLElement }) {
  const bubbles = [];
  new p5((sketch) => {
    let scanLineOffset;
    let scanLineOffStep = 5;
    const drawScan = (w = 24, x = 40, h = w, y = x, { color = '#34a76b', size = 5 } = {}) => {
      sketch.push();
      sketch.stroke(color);
      sketch.strokeWeight(size);

      // 左上角
      sketch.line(x, y, x + w, y);
      sketch.line(x, y, x, y + h);

      // 左下角
      sketch.line(x, height - y, x + w, height - y);
      sketch.line(x, height - y, x, height - y - h);

      // 右上角
      sketch.line(width - x, y, width - x - w, y);
      sketch.line(width - x, y, width - x, y + h);

      // 右下角
      sketch.line(width - x, height - y, width - x - w, height - y);
      sketch.line(width - x, height - y, width - x, height - y - h);

      // 线
      const yT = y * 2;
      const yB = height - yT;

      scanLineOffset ??= yT;

      if ( scanLineOffset < yT || scanLineOffset > yB ) scanLineOffStep = -scanLineOffStep;
      scanLineOffset += scanLineOffStep;

      sketch.line(x, scanLineOffset, width - x, scanLineOffset);

      sketch.pop();
    };

    const bubbles: Bubble[] = [
      { text: '有气\n无力', color: '#367dd599' },
      { text: '容易\n犯困', color: '#b1450399' },
      { text: '睡眠\n障碍', color: '#34b10399' },
      { text: '消化\n不良', color: '#b1860399' },
      { text: '肩颈\n腰痛', color: '#03b19b99' },
      { text: '掉\n头发', color: '#b1a30399' },
      { text: '记忆力\n下降', color: '#34b10399' },
    ];
    const drawBubble = (x = 40, y = x, diameter = 90) => {
      for ( const bubble of <Required<Bubble>[]> bubbles ) {
        bubble.diameter ??= diameter;
        const radius = Math.floor(bubble.diameter / 2);

        bubble.x ??= sketch.random(x + radius, width - x - radius);
        bubble.y ??= sketch.random(y + radius, height - y - radius);
        bubble.dx ??= sketch.random(-2, 2);
        bubble.dy ??= sketch.random(-2, 2);

        // 移动
        bubble.x += bubble.dx;
        bubble.y += bubble.dy;
        if ( bubble.x + radius >= width - y ) bubble.x = width - y;
        if ( bubble.y + radius >= height - y ) bubble.y = height - y;
        // 绘制
        const size = 24;
        const color = sketch.color(bubble.color);
        sketch.push();
        sketch.fill('#fff');
        sketch.textSize(size);
        sketch.textAlign(sketch.CENTER);
        sketch.text(bubble.text, bubble.x, bubble.y - size / 4);
        sketch.fill(color);
        sketch.circle(bubble.x, bubble.y, bubble.diameter);
        sketch.pop();
        // 检测边界
        if ( bubble.x - radius <= x || bubble.x + radius >= width - x ) {
          bubble.dx *= -1;
          if ( bubble.x - radius <= x ) { bubble.x = x + radius; } else { bubble.x = width - x - radius; }
        }
        if ( bubble.y - radius <= y || bubble.y + radius >= height - y ) {
          bubble.dy *= -1;
          if ( bubble.y - radius <= y ) { bubble.y = y + radius; } else { bubble.y = height - y - radius; }
        }
      }
      const collide = (bubble: Required<Bubble>, other: Required<Bubble>) => {
        const radius = Math.floor(bubble.diameter / 2);

        let angle = sketch.atan2(other.y - bubble.y, other.x - bubble.x);
        let target = sketch.createVector(bubble.x, bubble.y);
        let a = p5.Vector.fromAngle(angle + sketch.PI, radius);
        let b = p5.Vector.fromAngle(angle, radius);

        bubble.x = target.x + a.x;
        bubble.y = target.y + a.y;
        other.x = target.x + b.x;
        other.y = target.y + b.y;
        bubble.dx *= -1;
        other.dx *= -1;
      };
      for ( let i = 0; i < bubbles.length; i++ ) {
        for ( let j = i + 1; j < bubbles.length; j++ ) {
          const bubble = bubbles[ i ] as Required<Bubble>;
          const other = bubbles[ j ] as Required<Bubble>;

          const d = sketch.dist(bubble.x, bubble.y, other.x, other.y);
          if ( d < bubble.diameter ) {
            collide(bubble, other);
            collide(other, bubble);
          }
        }
      }
    };

    sketch.setup = () => {
      sketch.createCanvas(width, height);
      sketch.noStroke();
    };
    sketch.draw = () => {
      sketch.clear();
      drawScan();
      drawBubble();
    };
  }, container);
}
</script>
<template>
  <div class="wrapper">
    <div class="fixed size-full" ref="container"></div>
    <div class="fixed flex flex-col size-full">
      <div class="flex-none" style="height: 85vh;">
        <img class="mx-auto h-full object-scale-down" style="width: 32vw;" src="@/assets/images/title.png" :alt="title">
      </div>
      <div class="flex-auto flex flex-col">
        <div class="flex-auto flex justify-center items-center">
          <van-button class="decorate" :loading @click="handle()">开始检测</van-button>
        </div>
        <div class="flex-none text-xl p-8 text-center" v-html="copyright"></div>
      </div>
    </div>
  </div>
</template>
<style scoped lang="scss">
.wrapper {
  background: url("@/assets/images/screen.png") no-repeat center / 100%;
}
</style>
