<template>
  <NConfigProvider :theme='theme' :theme-overrides='theme === null ? lightThemeOverrides : darkThemeOverrides'>
    <NScrollbar>
      <NFlex class='main' align='center' justify='center'>
        <NResult status='error' :title='error.code'>
          <template #default>
            <NCard>
              <NP>{{ error.message }}</NP>
            </NCard>
          </template>
          <template #icon>
            <NIcon size='80'>
              <triangleExclamation />
            </NIcon>
          </template>
          <template #footer>
            <NFlex justify='center'>
              <NButton v-ripple @click='goBack'>返回上一页</NButton>
              <NButton v-ripple @click='goHome'>带我回家</NButton>
            </NFlex>
          </template>
        </NResult>
      </NFlex>
    </NScrollbar>
  </NConfigProvider>
</template>
<script setup lang='jsx'>
import {
  RippleDirective as vRipple,
  triangleExclamation,
  isDark,
  privacyPolicy,
  bgParticlesNumber,
  bgInitialSize,
  bgMoveLimit,
  bgDuration,
  bgDrawConnections,
  bgMouseInteractionDistance,
  bgMouseGravity,
  bgDrawMouseConnections,
  bgRenderFrameRate,
  notification
} from '~/utils';
import {
  title
} from '~/house';
import {
  NButton,
  NText
} from 'naive-ui';
const theme = computed(() => (isDark.value ? darkTheme : null)),
  lightThemeOverrides = {
    common: {
      cardColor: 'rgba(255, 255, 255, 0.7)',
      modalColor: 'rgba(255, 255, 255, 0.7)'
    },
  },
  darkThemeOverrides = {
    common: {
      cardColor: 'rgba(44, 44, 50, 0.7)',
      modalColor: 'rgba(44, 44, 50, 0.7)'
    },
  },
  dotColor = computed(() => (isDark.value ? [225, 225, 225, 0.5] : [166, 126, 183, 0.6])),
  lineColor = computed(() => (isDark.value ? [225, 225, 225, 0.05] : [178, 182, 182, 0.4])),
  bgImage = computed(() => (isDark.value ? 'linear-gradient(45deg, #3f3251 2%, #002025 100%)' : 'linear-gradient(50deg, #fbc2eb 70%, #a6c1ee 30%)')),
  goBack = () => {
    useRouter().go(-1);
  },
  goHome = () => {
    useRouter().replace('/');
  },
  error = {
    code: useError().value.statusCode.toString(),
    message: useError().value.message
  };
useHead({
  titleTemplate: (titleChunk) => titleChunk ? titleChunk + ' | ' + title : title
});
onMounted(async () => {
  await nextTick();
    if (privacyPolicy.value === 'unshown') {
      notification.info({
        title: '本站使用Cookie和本地存储保证浏览体验，请知晓',
        content: () => (
          <NButton>
            <NText>查看隐私声明</NText>
          </NButton>
        ),
        duration: 2500,
        closable: false,
        keepAliveOnHover: true
      });
      privacyPolicy.value = 'shown'
    };
    let canvas = document.createElement('canvas'),
      ctx = canvas.getContext('2d'),
      maximumPossibleDistance, centerX, centerY, mousePositionX, mousePositionY, mouseElement, lines = 0,
      objects = [],
      initAnimation = function() {
        canvas.width = document.body.clientWidth;
        canvas.height = document.body.clientHeight;
        maximumPossibleDistance = Math.round(Math.sqrt(canvas.width ** 2 + canvas.height ** 2));
        centerX = Math.floor(canvas.width / 2);
        centerY = Math.floor(canvas.height / 2);
        objects.length = 0;
        clearCanvas();
        createParticles()
      },
      particlesNumber = bgParticlesNumber.value,
      initialSize = bgInitialSize.value,
      moveLimit = bgMoveLimit.value,
      durationMin = bgDuration.value[0],
      durationMax = bgDuration.value[1],
      drawConnections = bgDrawConnections.value,
      mouseInteractionDistance = bgMouseInteractionDistance.value,
      mouseGravity = bgMouseGravity.value,
      drawMouseConnections = bgDrawMouseConnections.value,
      red = dotColor.value[0],
      green = dotColor.value[1],
      blue = dotColor.value[2],
      opacity = dotColor.value[3],
      connectionRed = lineColor.value[0],
      connectionGreen = lineColor.value[1],
      connectionBlue = lineColor.value[2],
      connectionOpacity = lineColor.value[3],
      mouseConnectionRed = lineColor.value[0],
      mouseConnectionGreen = lineColor.value[1],
      mouseConnectionBlue = lineColor.value[2],
      mouseConnectionOpacity = lineColor.value[3],
      getRandomBetween = (a, b) => (Math.floor(Math.random() * b) + a),
      getDistance = (element1, element2) => {
        let difX = Math.round(Math.abs(element1.positionX - element2.positionX)),
          difY = Math.round(Math.abs(element1.positionY - element2.positionY));
        return Math.round(Math.sqrt(difX * difX + difY * difY))
      },
      Particle = class {
        constructor(positionX, positionY, size, red, green, blue, opacity) {
          this.positionX = positionX;
          this.positionY = positionY;
          this.size = size;
          this.duration = getRandomBetween(durationMin, durationMax);
          this.limit = moveLimit;
          this.timer = 0;
          this.red = red;
          this.green = green;
          this.blue = blue;
          this.opacity = opacity;
          this.color = `rgba(${this.red},${this.green},${this.blue},${this.opacity})`
        }
        animateTo(newX, newY) {
          let duration = this.duration;
          const animatePosition = (newPosition, currentPosition) => {
            let step;
            if (newPosition > currentPosition) {
              step = (newPosition - currentPosition) / duration;
              newPosition = currentPosition + step
            } else {
              step = (currentPosition - newPosition) / duration;
              newPosition = currentPosition - step
            }
            return newPosition
          };
          this.positionX = animatePosition(newX, this.positionX);
          this.positionY = animatePosition(newY, this.positionY);
          if (this.timer === this.duration) {
            this.calculateVector();
            this.timer = 0
          } else {
            this.timer++
          }
        }
        calculateVector() {
          let distance, newPosition = {};
          const particle = this;
          const getCoordinates = () => {
            newPosition.positionX = getRandomBetween(0, document.body.clientWidth);
            newPosition.positionY = getRandomBetween(0, document.body.clientHeight);
            distance = getDistance(particle, newPosition)
          };
          while (typeof distance === 'undefined' || distance > this.limit) {
            getCoordinates()
          }
          this.vectorX = newPosition.positionX;
          this.vectorY = newPosition.positionY
        }
        testInteraction() {
          if (!drawConnections) return;
          let closestElement, distanceToClosestElement = maximumPossibleDistance;
          for (let x = 0; x < objects.length; x++) {
            let testedObject = objects[x];
            let distance = getDistance(this, testedObject);
            if (distance < distanceToClosestElement && testedObject !== this) {
              distanceToClosestElement = distance;
              closestElement = testedObject
            }
          }
          if (closestElement) {
            ctx.beginPath();
            ctx.moveTo(this.positionX + this.size / 2, this.positionY + this.size / 2);
            ctx.lineTo(closestElement.positionX + closestElement.size * 0.5, closestElement.positionY + closestElement.size * 0.5);
            ctx.strokeStyle = `rgba(${connectionRed},${connectionGreen},${connectionBlue},${connectionOpacity})`;
            ctx.stroke();
            lines++
          }
        }
        updateAnimation() {
          this.animateTo(this.vectorX, this.vectorY);
          this.testInteraction();
          ctx.fillStyle = this.color;
          ctx.fillRect(this.positionX, this.positionY, this.size, this.size)
        }
      },
      MouseParticle = class {
        constructor(positionX, positionY, size, red, green, blue, opacity) {
          this.positionX = mousePositionX;
          this.positionY = mousePositionY;
          this.size = size;
          this.red = red;
          this.green = green;
          this.blue = blue;
          this.opacity = opacity;
          this.color = `rgba(${this.red},${this.green},${this.blue},${this.opacity})`
        }
        testInteraction() {
          if (mouseInteractionDistance === 0) return;
          let closestElements = [];
          for (let x = 0; x < objects.length; x++) {
            let testedObject = objects[x];
            let distance = getDistance(this, testedObject);
            if (distance < mouseInteractionDistance && testedObject !== this) {
              closestElements.push(objects[x])
            }
          }
          for (let x = 0; x < closestElements.length; x++) {
            if (drawMouseConnections) {
              let element = closestElements[x];
              ctx.beginPath();
              ctx.moveTo(this.positionX, this.positionY);
              ctx.lineTo(element.positionX + element.size * 0.5, element.positionY + element.size * 0.5);
              ctx.strokeStyle = `rgba(${mouseConnectionRed},${mouseConnectionGreen},${mouseConnectionBlue},${mouseConnectionOpacity})`;
              ctx.stroke();
              lines++
            }
            if (mouseGravity) {
              closestElements[x].vectorX = this.positionX;
              closestElements[x].vectorY = this.positionY
            }
          }
        }
        updateAnimation() {
          this.positionX = mousePositionX;
          this.positionY = mousePositionY;
          this.testInteraction()
        }
      },
      createParticles = () => {
        mouseElement = new MouseParticle(0, 0, initialSize, 255, 255, 255);
        for (let x = 0; x < particlesNumber; x++) {
          let randomX = Math.floor(Math.random() * document.body.clientWidth + 1),
            randomY = Math.floor(Math.random() * document.body.clientHeight + 1),
            particle = new Particle(randomX, randomY, initialSize, red, green, blue, opacity, );
          particle.calculateVector();
          objects.push(particle)
        }
      },
      updatePosition = () => {
        for (let x = 0; x < objects.length; x++) {
          objects[x].updateAnimation()
        }
        mouseElement.updateAnimation()
      },
      clearCanvas = () => {
        ctx.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight)
      },
      loop = () => {
        clearCanvas();
        updatePosition();
        document.getElementById('house').style.background = 'url(' + canvas.toDataURL() + ') no-repeat center center, ' + bgImage.value;
        setTimeout(loop, 1000 / bgRenderFrameRate.value)
      };
    window.addEventListener('resize', initAnimation);
    document.getElementById('house').addEventListener('mousemove', (e) => {
      mousePositionX = e.clientX;
      mousePositionY = e.clientY
    });
    initAnimation();
    loop();
});
</script>
<style lang='scss'>
@font-face {
  font-family: 'v-sans';
  src: url('~assets/.woff2') format('woff2');
}

@font-face {
  font-family: 'v-mono';
  src: url('~assets/.woff2') format('woff2');
}

#house {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: 0;
}

.n-base-wave {
  display: none;
}
</style>
<style scoped>
.main {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: 0;
}
</style>