// controls.js - Zoom, rotate and toggle controls

import { CONFIG, EARTH_CONFIG } from './constants.js';
import { updateZoomDisplay, showStatusMessage } from './ui.js';
import { toggleTerrain } from './earth.js';
import { reloadData, clearLockedObject } from './main.js';
import { toggleSatellites, toggleTrails, getShowSatellites, getSatelliteCount } from './satellites.js';
import { toggleCables, getShowCables } from './cables.js';

export let autoRotate = true;
export let zoomLevel = 1.0;
export let showTerrain = false;
export let isDragging = false;

let earthObj = null;

export function setupControls(camera, renderer, scene, earth) {
  earthObj = earth;
  setupZoomControls(camera);
  setupWheelZoom(camera, renderer);
  setupRotateControls(camera, earth);
  setupTerrainControls();
}

function setupZoomControls(camera) {
  let zoomInterval = null;
  let holdTimeout = null;
  let startTime = 0;
  const HOLD_THRESHOLD = 150;
  const LONG_PRESS_TICK = 50;
  const CLICK_STEP = 10;
  
  const MIN_PERCENT = CONFIG.minZoom * 100;
  const MAX_PERCENT = CONFIG.maxZoom * 100;
  
  function doZoomStep(direction) {
    let currentPercent = Math.round(zoomLevel * 100);
    let newPercent = direction > 0 ? currentPercent + CLICK_STEP : currentPercent - CLICK_STEP;
    
    if (newPercent > MAX_PERCENT) newPercent = MAX_PERCENT;
    if (newPercent < MIN_PERCENT) newPercent = MIN_PERCENT;
    
    zoomLevel = newPercent / 100;
    applyZoom(camera);
  }
  
  function doContinuousZoom(direction) {
    let currentPercent = Math.round(zoomLevel * 100);
    let newPercent = direction > 0 ? currentPercent + 1 : currentPercent - 1;
    
    if (newPercent > MAX_PERCENT) newPercent = MAX_PERCENT;
    if (newPercent < MIN_PERCENT) newPercent = MIN_PERCENT;
    
    zoomLevel = newPercent / 100;
    applyZoom(camera);
  }
  
  function startContinuousZoom(direction) {
    doContinuousZoom(direction);
    zoomInterval = setInterval(() => {
      doContinuousZoom(direction);
    }, LONG_PRESS_TICK);
  }
  
  function stopZoom() {
    if (zoomInterval) {
      clearInterval(zoomInterval);
      zoomInterval = null;
    }
    if (holdTimeout) {
      clearTimeout(holdTimeout);
      holdTimeout = null;
    }
  }
  
  function handleMouseDown(direction) {
    startTime = Date.now();
    stopZoom();
    holdTimeout = setTimeout(() => {
      startContinuousZoom(direction);
    }, HOLD_THRESHOLD);
  }
  
  function handleMouseUp(direction) {
    const heldTime = Date.now() - startTime;
    stopZoom();
    if (heldTime < HOLD_THRESHOLD) {
      doZoomStep(direction);
    }
  }
  
  document.getElementById('zoom-in').addEventListener('mousedown', () => handleMouseDown(1));
  document.getElementById('zoom-in').addEventListener('mouseup', () => handleMouseUp(1));
  document.getElementById('zoom-in').addEventListener('mouseleave', stopZoom);
  document.getElementById('zoom-in').addEventListener('touchstart', (e) => { e.preventDefault(); handleMouseDown(1); });
  document.getElementById('zoom-in').addEventListener('touchend', () => handleMouseUp(1));
  
  document.getElementById('zoom-out').addEventListener('mousedown', () => handleMouseDown(-1));
  document.getElementById('zoom-out').addEventListener('mouseup', () => handleMouseUp(-1));
  document.getElementById('zoom-out').addEventListener('mouseleave', stopZoom);
  document.getElementById('zoom-out').addEventListener('touchstart', (e) => { e.preventDefault(); handleMouseDown(-1); });
  document.getElementById('zoom-out').addEventListener('touchend', () => handleMouseUp(-1));
  
  document.getElementById('zoom-value').addEventListener('click', function() {
    const startZoomVal = zoomLevel;
    const targetZoom = 1.0;
    const startDistance = CONFIG.defaultCameraZ / startZoomVal;
    const targetDistance = CONFIG.defaultCameraZ / targetZoom;
    
    animateValue(0, 1, 600, (progress) => {
      const ease = 1 - Math.pow(1 - progress, 3);
      zoomLevel = startZoomVal + (targetZoom - startZoomVal) * ease;
      camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
      const distance = startDistance + (targetDistance - startDistance) * ease;
      updateZoomDisplay(zoomLevel, distance.toFixed(0));
    }, () => {
      zoomLevel = 1.0;
      showStatusMessage('缩放已重置到100%', 'info');
    });
  });
}

function setupWheelZoom(camera, renderer) {
  renderer.domElement.addEventListener('wheel', (e) => {
    e.preventDefault();
    if (e.deltaY < 0) {
      zoomLevel = Math.min(zoomLevel + 0.1, CONFIG.maxZoom);
    } else {
      zoomLevel = Math.max(zoomLevel - 0.1, CONFIG.minZoom);
    }
    applyZoom(camera);
  }, { passive: false });
}

function applyZoom(camera) {
  camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
  const distance = camera.position.z.toFixed(0);
  updateZoomDisplay(zoomLevel, distance);
}

function animateValue(start, end, duration, onUpdate, onComplete) {
  const startTime = performance.now();
  
  function update(currentTime) {
    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / duration, 1);
    const easeProgress = 1 - Math.pow(1 - progress, 3);
    
    const current = start + (end - start) * easeProgress;
    onUpdate(current);
    
    if (progress < 1) {
      requestAnimationFrame(update);
    } else if (onComplete) {
      onComplete();
    }
  }
  
  requestAnimationFrame(update);
}

export function resetView(camera) {
  if (!earthObj) return;
  
  function animateToView(targetLat, targetLon, targetRotLon) {
    const latRot = targetLat * Math.PI / 180;
    const targetRotX = EARTH_CONFIG.tiltRad + latRot * EARTH_CONFIG.latCoefficient;
    const targetRotY = -(targetRotLon * Math.PI / 180);
    
    const startRotX = earthObj.rotation.x;
    const startRotY = earthObj.rotation.y;
    const startZoom = zoomLevel;
    const targetZoom = 1.0;
    
    animateValue(0, 1, 800, (progress) => {
      const ease = 1 - Math.pow(1 - progress, 3);
      earthObj.rotation.x = startRotX + (targetRotX - startRotX) * ease;
      earthObj.rotation.y = startRotY + (targetRotY - startRotY) * ease;
      
      zoomLevel = startZoom + (targetZoom - startZoom) * ease;
      camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
      updateZoomDisplay(zoomLevel, camera.position.z.toFixed(0));
    }, () => {
      zoomLevel = 1.0;
      showStatusMessage('视角已重置', 'info');
    });
  }
  
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
      (pos) => animateToView(pos.coords.latitude, pos.coords.longitude, -pos.coords.longitude),
      () => animateToView(EARTH_CONFIG.chinaLat, EARTH_CONFIG.chinaLon, EARTH_CONFIG.chinaRotLon),
      { timeout: 5000, enableHighAccuracy: false }
    );
  } else {
    animateToView(EARTH_CONFIG.chinaLat, EARTH_CONFIG.chinaLon, EARTH_CONFIG.chinaRotLon);
  }
  
  if (typeof window.clearLockedCable === 'function') {
    window.clearLockedCable();
  }
}

function setupRotateControls(camera, earth) {
  const rotateBtn = document.getElementById('rotate-toggle');
  
  rotateBtn.addEventListener('click', function() {
    const isRotating = toggleAutoRotate();
    showStatusMessage(isRotating ? '自动旋转已开启' : '自动旋转已暂停', 'info');
  });
  
  updateRotateUI();
  
  document.getElementById('reset-view').addEventListener('click', function() {
    resetView(camera);
  });
}

function setupTerrainControls() {
  document.getElementById('toggle-terrain').addEventListener('click', function() {
    showTerrain = !showTerrain;
    toggleTerrain(showTerrain);
    this.classList.toggle('active', showTerrain);
    this.querySelector('.tooltip').textContent = showTerrain ? '隐藏地形' : '显示地形';
    document.getElementById('terrain-status').textContent = showTerrain ? '开启' : '关闭';
    showStatusMessage(showTerrain ? '地形已显示' : '地形已隐藏', 'info');
  });
  
  document.getElementById('toggle-satellites').addEventListener('click', function() {
    const showSats = !getShowSatellites();
    if (!showSats) {
      clearLockedObject();
    }
    toggleSatellites(showSats);
    this.classList.toggle('active', showSats);
    this.querySelector('.tooltip').textContent = showSats ? '隐藏卫星' : '显示卫星';
    document.getElementById('satellite-count').textContent = getSatelliteCount() + ' 颗';
    showStatusMessage(showSats ? '卫星已显示' : '卫星已隐藏', 'info');
  });
  
  document.getElementById('toggle-trails').addEventListener('click', function() {
    const isActive = this.classList.contains('active');
    const showTrails = !isActive;
    toggleTrails(showTrails);
    this.classList.toggle('active', showTrails);
    this.querySelector('.tooltip').textContent = showTrails ? '隐藏轨迹' : '显示轨迹';
    showStatusMessage(showTrails ? '轨迹已显示' : '轨迹已隐藏', 'info');
  });
  
  document.getElementById('toggle-cables').addEventListener('click', function() {
    const showCables = !getShowCables();
    if (!showCables) {
      clearLockedObject();
    }
    toggleCables(showCables);
    this.classList.toggle('active', showCables);
    this.querySelector('.tooltip').textContent = showCables ? '隐藏线缆' : '显示线缆';
    showStatusMessage(showCables ? '线缆已显示' : '线缆已隐藏', 'info');
  });
  
  document.getElementById('reload-data').addEventListener('click', async () => {
    await reloadData();
    showStatusMessage('数据已重新加载', 'success');
  });
  
  const toolbarToggle = document.getElementById('toolbar-toggle');
  const toolbar = document.getElementById('control-toolbar');
  if (toolbarToggle && toolbar) {
    toolbarToggle.addEventListener('click', () => {
      toolbar.classList.toggle('collapsed');
    });
  }
}

export function getAutoRotate() {
  return autoRotate;
}

function updateRotateUI() {
  const btn = document.getElementById('rotate-toggle');
  if (btn) {
    btn.classList.toggle('active', autoRotate);
    btn.innerHTML = autoRotate ? '⏸️' : '▶️';
    const tooltip = btn.querySelector('.tooltip');
    if (tooltip) tooltip.textContent = autoRotate ? '暂停旋转' : '开始旋转';
  }
}

export function setAutoRotate(value) {
  autoRotate = value;
  updateRotateUI();
}

export function toggleAutoRotate() {
  autoRotate = !autoRotate;
  updateRotateUI();
  if (window.clearLockedCable) {
    window.clearLockedCable();
  }
  return autoRotate;
}

export function getZoomLevel() {
  return zoomLevel;
}

export function getShowTerrain() {
  return showTerrain;
}
