// earth.js - 3D Earth creation module

import * as THREE from 'three';
import { CONFIG, EARTH_CONFIG } from './constants.js';
import { latLonToVector3 } from './utils.js';

export let earth = null;
export let clouds = null;
export let terrain = null;

const textureLoader = new THREE.TextureLoader();

export function createEarth(scene) {
  const geometry = new THREE.SphereGeometry(CONFIG.earthRadius, 128, 128);
  
  const material = new THREE.MeshPhongMaterial({
    color: 0xffffff,
    specular: 0x111111,
    shininess: 10,
    emissive: 0x000000,
    transparent: true,
    opacity: 0.8,
    side: THREE.DoubleSide
  });
   
  earth = new THREE.Mesh(geometry, material);
  earth.rotation.x = EARTH_CONFIG.tiltRad;
  scene.add(earth);
  
  const textureUrls = [
    './assets/8k_earth_daymap.jpg',
    'https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/planets/earth_atmos_2048.jpg',
    'https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg',
    'https://assets.codepen.io/982762/earth_texture_2048.jpg'
  ];
  
  let textureLoaded = false;
  
  textureLoader.load(
    textureUrls[0],
    function(texture) {
      console.log('高分辨率地球纹理加载成功');
      textureLoaded = true;
      
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.ClampToEdgeWrapping;
      texture.anisotropy = 16;
      texture.minFilter = THREE.LinearMipmapLinearFilter;
      texture.magFilter = THREE.LinearFilter;
      
      material.map = texture;
      material.needsUpdate = true;
      
      document.getElementById('loading').style.display = 'none';
    },
    function(xhr) {
      console.log('纹理加载中: ' + (xhr.loaded / xhr.total * 100) + '%');
    },
    function(err) {
      console.log('第一个纹理加载失败，尝试第二个...');
      
      textureLoader.load(
        textureUrls[1],
        function(texture) {
          console.log('第二个纹理加载成功');
          textureLoaded = true;
          
          texture.wrapS = THREE.RepeatWrapping;
          texture.wrapT = THREE.ClampToEdgeWrapping;
          texture.anisotropy = 16;
          texture.minFilter = THREE.LinearMipmapLinearFilter;
          texture.magFilter = THREE.LinearFilter;
          
          material.map = texture;
          material.needsUpdate = true;
          
          document.getElementById('loading').style.display = 'none';
        },
        null,
        function(err) {
          console.log('所有纹理加载失败');
          document.getElementById('loading').style.display = 'none';
        }
      );
    }
  );
  
  return earth;
}

export function createClouds(scene, earthObj) {
  const geometry = new THREE.SphereGeometry(CONFIG.earthRadius + 3, 64, 64);
  const material = new THREE.MeshPhongMaterial({
    transparent: true,
    linewidth: 2,
    opacity: 0.15,
    depthTest: true,
    depthWrite: false,
    blending: THREE.AdditiveBlending,
    side: THREE.DoubleSide
  });
  
  clouds = new THREE.Mesh(geometry, material);
  earthObj.add(clouds);
  
  textureLoader.load(
    'https://threejs.org/examples/textures/planets/earth_clouds_1024.png',
    function(texture) {
      material.map = texture;
      material.needsUpdate = true;
    },
    undefined,
    function(err) {
      console.log('云层纹理加载失败');
    }
  );
  
  return clouds;
}

export function createTerrain(scene, earthObj, simplex) {
  const geometry = new THREE.SphereGeometry(CONFIG.earthRadius, 128, 128);
  const positionAttribute = geometry.getAttribute('position');
  
  for (let i = 0; i < positionAttribute.count; i++) {
    const x = positionAttribute.getX(i);
    const y = positionAttribute.getY(i);
    const z = positionAttribute.getZ(i);
    
    const noise = simplex(x / 20, y / 20, z / 20);
    const height = 1 + noise * 0.02;
    
    positionAttribute.setXYZ(i, x * height, y * height, z * height);
  }
  
  geometry.computeVertexNormals();
  
  const material = new THREE.MeshPhongMaterial({
    color: 0x00aa00,
    flatShading: true,
    transparent: true,
    opacity: 0.7
  });
  
  terrain = new THREE.Mesh(geometry, material);
  terrain.visible = false;
  earthObj.add(terrain);
  
  return terrain;
}

export function toggleTerrain(visible) {
  if (terrain) {
    terrain.visible = visible;
  }
}

export function createStars(scene) {
  const starGeometry = new THREE.BufferGeometry();
  const starCount = 8000;
  const starPositions = new Float32Array(starCount * 3);
  
  for (let i = 0; i < starCount * 3; i += 3) {
    const r = 800 + Math.random() * 200;
    const theta = Math.random() * Math.PI * 2;
    const phi = Math.acos(2 * Math.random() - 1);
    
    starPositions[i] = r * Math.sin(phi) * Math.cos(theta);
    starPositions[i + 1] = r * Math.sin(phi) * Math.sin(theta);
    starPositions[i + 2] = r * Math.cos(phi);
  }
  
  starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
  
  const starMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.5,
    transparent: true,
    blending: THREE.AdditiveBlending
  });
  
  const stars = new THREE.Points(starGeometry, starMaterial);
  scene.add(stars);
  
  return stars;
}

let latitudeLines = [];
let longitudeLines = [];

export function createGridLines(scene, earthObj) {
  latitudeLines.forEach(line => scene.remove(line));
  longitudeLines.forEach(line => scene.remove(line));
  latitudeLines = [];
  longitudeLines = [];
  
  const earthRadius = 100.1;
  const gridMaterial = new THREE.LineBasicMaterial({
    color: 0x44aaff,
    transparent: true,
    opacity: 0.2,
    linewidth: 1
  });
  
  for (let lat = -75; lat <= 75; lat += 15) {
    const points = [];
    for (let lon = -180; lon <= 180; lon += 5) {
      const point = latLonToVector3(lat, lon, earthRadius);
      points.push(point);
    }
    
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const line = new THREE.Line(geometry, gridMaterial);
    line.userData = { type: 'latitude', value: lat };
    earthObj.add(line);
    latitudeLines.push(line);
  }
  
  for (let lon = -180; lon <= 180; lon += 30) {
    const points = [];
    for (let lat = -90; lat <= 90; lat += 5) {
      const point = latLonToVector3(lat, lon, earthRadius);
      points.push(point);
    }
    
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const line = new THREE.Line(geometry, gridMaterial);
    line.userData = { type: 'longitude', value: lon };
    earthObj.add(line);
    longitudeLines.push(line);
  }
}

export function getEarth() {
  return earth;
}

export function getClouds() {
  return clouds;
}
