import * as THREE from 'three'
import { CSS2DObjct, CSS2DRenderer } from './CSS2DRender'
import { OrbitControls } from './OrbitControls'

export class EarthAndMoon {
  scene: THREE.Scene
  camera: THREE.PerspectiveCamera
  renderer: THREE.Renderer
  twoDRenderer: CSS2DRenderer

  worldWidth: number
  worldHeight: number
  textureLoader: THREE.TextureLoader
  clock: THREE.Clock
  moon: THREE.Mesh
  constructor() {

    this.textureLoader = new THREE.TextureLoader()
    this.clock = new THREE.Clock()
    this.initScene()
    this.initCamera()
    this.initGeometry()
    this.initRenderer()
    this.initEvents()
    this.loop()
  }

  /**
   * 初始化场景
   */
  initScene() {
    this.worldHeight = window.innerHeight
    this.worldWidth = window.innerWidth
    const scene = this.scene = new THREE.Scene()
    // 创建 平行光， Three 里面的 光也会是有着很多种的， 比如 PointLight 点光源, DirectionalLight 平行光, SpotLight 聚光灯, AmbientLight 环境光
    // 这里的 是模拟太阳光 平行光就 十分合适
    const dirLight = new THREE.DirectionalLight(0xffffff)
    dirLight.position.set(1, 1, 1)
    scene.add(dirLight)

    // 创建 debug的 坐标
    scene.add(new THREE.AxesHelper(5))
    // 创建光源debug
    scene.add(new THREE.DirectionalLightHelper(dirLight))
  }

  /**
   * 初始化相机
   */
  initCamera() {
    // 投影矩阵 
    // THREE.OrthographicCamera()
    this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200)
    this.camera.position.set(10, 5, 20)
    this.camera.lookAt(this.scene.position)
  }

  /**
   * 初始化渲染器
   */
  initRenderer() {
    // 创建WebGL渲染器
    const renderer = this.renderer = new THREE.WebGLRenderer()
    renderer.setPixelRatio( window.devicePixelRatio );
    this.renderer.setSize(this.worldWidth, this.worldHeight)
    // 把renderer的 domElement 添加到 网页中
    document.body.appendChild(this.renderer.domElement)

    // 创建 CSS2D 渲染器
    // CSS2DRenderer 这里面主要会有一个 render方法 通过入参 scene和 camera 来对 特定的Dom进行CSS渲染设置
    // const _css2dRenderer = this.twoDRenderer = new CSS2DRenderer()
    // _css2dRenderer.setSize( window.innerWidth, window.innerHeight );
    // _css2dRenderer.domElement.style.position = 'absolute';
    // _css2dRenderer.domElement.style.top = '0px';
    // document.body.appendChild( _css2dRenderer.domElement );

    // OrbitControls Three 自带的 鼠标控制器,这里的入参就是 我们的相机
    // const controls = new OrbitControls(this.camera, this.renderer.domElement)
    // controls.minDistance = 5;
    // controls.maxDistance = 100;
  }

  /**
   * 初始化事件
   */
  initEvents() {
    window.addEventListener( 'resize', () => {
      // 计算 camera的角度值
      this.camera.aspect = window.innerWidth / window.innerHeight;
      // 更新 camerade 的投影矩阵
      this.camera.updateProjectionMatrix();

      this.renderer.setSize( window.innerWidth, window.innerHeight );

      // this.twoDRenderer.setSize( window.innerWidth, window.innerHeight );
    });
  }

  /**
   * 初始化几何体
   */
  initGeometry() {
    this.initEarthGeometry()
    this.initMoonGeometry()
  }

  /**
   * 初始化地球几何体
   */
  initEarthGeometry() {
    const textureLoader = this.textureLoader
    // 创建球体
    const earthGeometry = new THREE.SphereGeometry(1, 16, 16)
    // MeshPhongMaterial 高光纹理，可以进行光照的漫反射和镜面反射
    const earthMaterial = new THREE.MeshPhongMaterial({
      specular: 0x333333, // 反光
      shininess: 5, // 反光范围
      map: textureLoader.load('./earth_atmos_2048.jpg'), // 地球上的贴图
      specularMap: textureLoader.load( './earth_specular_2048.jpg' ),
      normalMap: textureLoader.load( './earth_normal_2048.jpg' ),
      normalScale: new THREE.Vector2( 0.85, 0.85 )
    })
    // 创建地球 THREE.Mesh 入参就是 几何体和 纹理
    const earthMesh = new THREE.Mesh(earthGeometry, earthMaterial)
    this.scene.add(earthMesh)

    // CSS2DObjct 继承 Object3D 所以就可以 通过 add方法 添加到场景中,这里就直接加入到 earthMesh中 后面就可以通过 
    // twoDRenderer 进行渲染， 因为这里面会有着 isCSS2DObject 来进行区分
    // const earthLabel = new CSS2DObjct(document.createElement('div'), {
    //   marginTop: '-1em',
    //   color: '#fff',
    // }, {
    //   className: 'label',
    //   textContent: 'Earth'
    // })
    // earthLabel.position.set( 0, 1, 0 );
    // earthMesh.add(earthLabel)
  }

  /**
   * 初始化月球几何体
   */
  initMoonGeometry() {
    // 下面就基本和 地球是一致的
    const textureLoader = this.textureLoader
    const moonGeometry = new THREE.SphereGeometry(0.75, 16, 16)
    const moonMaterial = new THREE.MeshPhongMaterial({
      shininess: 5, // 反光范围
      map: textureLoader.load('./moon_1024.jpg'),
    })
    const moonMesh = this.moon = new THREE.Mesh(moonGeometry, moonMaterial)
    moonMesh.position.x = 3
    this.scene.add(moonMesh)

    // const moonLabel = new CSS2DObjct(document.createElement('div'), {marginTop: '-1em',
    // color: '#fff',}, {
    //   className: 'label',
    //   textContent: 'Moon'
    // })
    // moonLabel.position.set(0, 0.75, 0)
    // moonMesh.add(moonLabel)
  }

  /**
   * 帧回调
   */
  loop() {
    const elapsed = this.clock.getElapsedTime();
    // 计算月球的位置
    this.moon.position.set( Math.sin( elapsed ) * 5, 0, Math.cos( elapsed ) * 5 );
    this.renderer.render(this.scene, this.camera)
    // this.twoDRenderer.render(this.scene, this.camera)
    requestAnimationFrame(this.loop.bind(this))
  }
}

new EarthAndMoon()