<template>
  <div>
    <video
      id="video"
      :src="mediaSource"
      style="display: none"
      loop
      crossorigin="anonymous"
    ></video>
    <canvas id="canvas"></canvas>
    <div class="play-button" v-show="!isPlaying" @click="handleClick">
      <i class="play-icon"></i>
    </div>
    <div class="upload-container">
      <input
        type="file"
        ref="fileInput"
        @change="handleFileUpload"
        accept="image/*,video/*"
        style="display: none"
      />
      <button class="upload-btn" @click="triggerFileUpload">
        {{ $t('shader.uploadImageVideo') }}
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import * as THREE from "three";
import { onMounted, onUnmounted, ref } from "vue";

const isPlaying = ref(false);
const fileInput = ref<HTMLInputElement | null>(null);
const mediaSource = ref("/static/test.mp4");
const isVideo = ref(true);
const texture = ref<THREE.VideoTexture | THREE.Texture | null>(null);

const triggerFileUpload = () => {
  fileInput.value?.click();
};

const handleClick = () => {
  if (isVideo.value) {
    const video = document.getElementById("video") as HTMLVideoElement;
    video.play();
    isPlaying.value = true;
  }
};

const createImageTexture = (url: string): Promise<THREE.Texture> => {
  return new Promise((resolve) => {
    const loader = new THREE.TextureLoader();
    loader.load(url, (texture) => {
      texture.minFilter = THREE.LinearFilter;
      texture.magFilter = THREE.LinearFilter;
      resolve(texture);
    });
  });
};

const handleFileUpload = async (event: Event) => {
  const input = event.target as HTMLInputElement;
  const file = input.files?.[0];

  if (file) {
    const url = URL.createObjectURL(file);
    const video = document.getElementById("video") as HTMLVideoElement;

    // 先暂停当前播放
    video.pause();
    isPlaying.value = false;

    if (file.type.startsWith("video/")) {
      isVideo.value = true;
      // 更新视频源
      mediaSource.value = url;

      // 如果是视频，等待加载后再播放
      video.addEventListener(
        "loadeddata",
        async () => {
          try {
            texture.value = new THREE.VideoTexture(video);
            texture.value.minFilter = THREE.LinearFilter;
            texture.value.magFilter = THREE.LinearFilter;
            texture.value.format = THREE.RGBFormat;
            await video.play();
            isPlaying.value = true;
          } catch (err) {
            console.error("视频播放失败:", err);
            isPlaying.value = false;
          }
        },
        { once: true }
      );
    } else if (file.type.startsWith("image/")) {
      isVideo.value = false;
      mediaSource.value = "";
      // 创建图片纹理
      texture.value = await createImageTexture(url);
    }

    // 重置文件输入，允许重复上传相同文件
    input.value = "";
  }
};

// 创建场景和相机
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 5;

onMounted(async () => {
  const renderer = new THREE.WebGLRenderer({
    canvas: document.querySelector("#canvas"),
  });
  renderer.setSize(window.innerWidth, window.innerHeight);

  // 获取视频元素
  const video = document.getElementById("video") as HTMLVideoElement;

  // 创建初始视频纹理
  texture.value = new THREE.VideoTexture(video);
  texture.value.minFilter = THREE.LinearFilter;
  texture.value.magFilter = THREE.LinearFilter;
  texture.value.format = THREE.RGBFormat;

  // 等待视频加载完成后播放
  video.addEventListener(
    "loadeddata",
    async () => {
      try {
        await video.play();
        isPlaying.value = true;
      } catch (err) {
        console.error("视频播放失败:", err);
        isPlaying.value = false;
      }
    },
    { once: true }
  );

  // 创建平面几何体
  const geometry = new THREE.PlaneGeometry(10, 10, 200, 200);

  // 创建 ShaderMaterial
  const material = new THREE.ShaderMaterial({
    vertexShader: `
          varying vec2 vUv;
          varying float vDist;
          varying float vRandom;
          uniform vec2 mouse;
          uniform float radius;
          uniform float time;
          uniform float drag;

          // 随机函数
          float random(vec2 st) {
              return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
          }

          void main() {
              vUv = uv;
              vec3 pos = position;
              
              // 基于位置和时间生成随机值
              float rand = random(pos.xy) * 1.01 - 0.01;
              vRandom = rand;
              
              // 计算打散效果
              float disperseFactor = sin(time * 0.5) * 0.00001;
              vec3 disperseDir = vec3(
                  rand * disperseFactor,
                  rand * disperseFactor,
                  0
              );
              
              // 鼠标交互
              vec2 mouseDir = pos.xy - mouse;
              float dist = length(mouseDir);

              if (dist < radius) {
                  float force = (radius - dist) / radius;
                  pos.xy += normalize(mouseDir) * force * 0.5;
              }

              // 应用打散效果
              pos += disperseDir;
              
              // 减小粒子大小
              gl_PointSize = 3.0 * (1.0 + random(pos.xy));

              vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
              gl_Position = projectionMatrix * mvPosition;
              
              vDist = dist;
          }`,
    fragmentShader: `
          uniform sampler2D mainTexture;
          varying vec2 vUv;
          varying float vDist;
          varying float vRandom;
          uniform float time;

          // 颜色调整辅助函数
          vec3 adjustColor(vec3 color) {
              // 增加对比度
              vec3 contrast = (color - 0.5) * 1.4 + 0.5;
              
              // 计算亮度
              float luminance = dot(contrast, vec3(0.299, 0.587, 0.114));
              
              // 增加饱和度
              vec3 saturated = mix(vec3(luminance), contrast, 1.3);
              
              // 稍微压暗高光
              saturated = pow(saturated, vec3(1.1));
              
              return saturated;
          }

          void main() {
              // 马赛克大小
              float mosaicSize = 1000.0;
              vec2 mosaicUv = floor(vUv * mosaicSize) / mosaicSize;
              
              // 减小抖动效果
              float jitter = sin(time * 2.0 + vRandom * 1.28) * 0.001;
              mosaicUv += vec2(jitter);

              vec4 texColor = texture2D(mainTexture, mosaicUv);
              
              // 调整颜色
              vec3 adjustedColor = adjustColor(texColor.rgb);
              
              // 调整扭曲和淡出效果
              float distortionFactor = 1.0 - vDist * 0.005;
              float alpha = 0.99 + 0.01 * sin(time * 2.0 + vRandom * 6.28);
              
              // 边缘淡出效果
              float edgeFade = 1.0 - length(gl_PointCoord - vec2(0.5)) * 2.0;
              edgeFade = smoothstep(0.0, 0.5, edgeFade);

              gl_FragColor = vec4(adjustedColor, texColor.a * alpha * edgeFade);
          }`,
    uniforms: {
      mainTexture: { value: texture.value },
      mouse: { value: new THREE.Vector2(0, 0) },
      radius: { value: 0.5 },
      time: { value: 0 },
      drag: { value: 0.98 },
    },
    transparent: true,
    side: THREE.DoubleSide,
    depthWrite: false,
    blending: THREE.AdditiveBlending,
  });

  // 创建平面点云
  const points = new THREE.Points(geometry, material);
  scene.add(points);

  // 鼠标事件监听
  const mouse = new THREE.Vector2();
  const rect = renderer.domElement.getBoundingClientRect();
  document.addEventListener("mousemove", (event) => {
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    material.uniforms.mouse.value.set(mouse.x * 5, mouse.y * 5);
  });

  // 动画更新
  function animate() {
    requestAnimationFrame(animate);

    if (texture.value) {
      if (isVideo.value && video.readyState === video.HAVE_ENOUGH_DATA) {
        (texture.value as THREE.VideoTexture).needsUpdate = true;
      }
      material.uniforms.mainTexture.value = texture.value;
    }

    material.uniforms.time.value += 0.016;
    renderer.render(scene, camera);
  }
  animate();

  // 窗口大小改变时更新
  window.addEventListener("resize", () => {
    const width = window.innerWidth;
    const height = window.innerHeight;

    camera.aspect = width / height;
    camera.updateProjectionMatrix();

    renderer.setSize(width, height);
  });

  // 监听视频暂停事件
  video.addEventListener("pause", () => {
    isPlaying.value = false;
  });

  // 监听视频播放事件
  video.addEventListener("play", () => {
    isPlaying.value = true;
  });
});

// 组件卸载时清理
onUnmounted(() => {
  const video = document.getElementById("video") as HTMLVideoElement;
  video.pause();
  video.src = "";
  video.load();

  // 清理创建的对象URL
  if (mediaSource.value.startsWith("blob:")) {
    URL.revokeObjectURL(mediaSource.value);
  }

  // 清理纹理
  if (texture.value) {
    texture.value.dispose();
    texture.value = null;
  }
});
</script>

<style scoped>
canvas {
  width: 100vw;
  height: 100vh;
  display: block;
}

.play-button {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80px;
  height: 80px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s;
}

.play-button:hover {
  background: rgba(0, 0, 0, 0.8);
  transform: translate(-50%, -50%) scale(1.1);
}

.play-icon {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 20px 0 20px 30px;
  border-color: transparent transparent transparent #ffffff;
  margin-left: 8px;
}

.upload-container {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
}

.upload-btn {
  background: rgba(0, 0, 0, 0.6);
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 20px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s;
}

.upload-btn:hover {
  background: rgba(0, 0, 0, 0.8);
  transform: scale(1.05);
}
</style>
