import { SCREEN_WIDTH, SCREEN_HEIGHT, SAFE_AREA_BOTTOM } from '../render';
import { BUBBLE_RADIUS, getActiveColorCount, drawBubble3D } from './bubble';
import FireBubble from './fireBubble';

// 鸡的尺寸（相对泡泡半径）
const CHICKEN_WIDTH  = BUBBLE_RADIUS * 5;
const CHICKEN_HEIGHT = BUBBLE_RADIUS * 6;
// 鸡底部距屏幕底部的距离
const CHICKEN_BOTTOM_MARGIN = BUBBLE_RADIUS * 0.8;
// 泡泡在鸡头顶上方的偏移
const BUBBLE_TOP_OFFSET = BUBBLE_RADIUS * 0.4;
// 下一颗泡泡相对当前泡泡的偏移
const NEXT_X_OFFSET = BUBBLE_RADIUS * 3.8;
const NEXT_Y_OFFSET = BUBBLE_RADIUS * -1.5;
// 下一颗泡泡的缩放比例
const NEXT_SCALE = 0.65;
// 发射速度（px/帧）
const FIRE_SPEED = 18;
// 发射角度限制（相对水平轴，单位弧度），防止近乎水平射出
const MIN_ANGLE = 15 * Math.PI / 180;
const MAX_ANGLE = 165 * Math.PI / 180;

// ─── 鸡朝向参数 ───
// 鸡身体最大倾斜角度（瞄准到最左/最右时的倾斜）
const MAX_LEAN_ANGLE = 25 * Math.PI / 180;
// 鸡倾斜的平滑插值速度（0~1，越大越跟手）
const LEAN_LERP = 0.15;
// 待机时上下呼吸浮动
const BOB_SPEED = 0.04;
const BOB_AMOUNT = BUBBLE_RADIUS * 0.2;

// ─── 发射弹跳动画参数 ───
const SQUASH_DURATION  = 6;
const STRETCH_DURATION = 4;
const RECOVER_DURATION = 8;
const SQUASH_SCALE_Y   = 0.6;
const SQUASH_SCALE_X   = 1.3;
const STRETCH_SCALE_Y  = 1.15;
const STRETCH_SCALE_X  = 0.85;

// 加载鸡图片（模块级单例）
const _chickenImg = wx.createImage();
_chickenImg.src = 'images/chicken.png';

function easeOutCubic(t) {
  return 1 - Math.pow(1 - t, 3);
}

function easeInCubic(t) {
  return t * t * t;
}

/**
 * 底部射击器类 — 鸡造型
 * 鸡身体朝向跟随手指瞄准方向倾斜，没瞄准时站直微微呼吸浮动。
 */
export default class Shooter {
  constructor() {
    this.x = SCREEN_WIDTH / 2;
    this._chickenBottom = SCREEN_HEIGHT - SAFE_AREA_BOTTOM - CHICKEN_BOTTOM_MARGIN;
    this._chickenCenterY = this._chickenBottom - CHICKEN_HEIGHT / 2;
    this.y = this._chickenBottom - CHICKEN_HEIGHT - BUBBLE_TOP_OFFSET;

    this.currentColor = this._randomColor();
    this.nextColor = this._randomColor();

    // 瞄准状态
    this._isAiming = false;
    this._aimAngle = Math.PI / 2;
    this._aimPoints = [];

    // 鸡当前倾斜角度（平滑插值用）
    this._currentLean = 0;
    // 上下呼吸浮动相位
    this._bobPhase = 0;

    // 发射弹跳动画状态
    this._bounceFrame = -1;
    this._bounceScaleX = 1;
    this._bounceScaleY = 1;
    this._bounceOffsetY = 0;

    this._bindEvents();
  }

  _randomColor() {
    return Math.floor(Math.random() * getActiveColorCount(GameGlobal.databus.score)) + 1;
  }

  advance() {
    this.currentColor = this.nextColor;
    this.nextColor = this._randomColor();
  }

  // ─── 事件绑定 ─────────────────────────────────────────────

  _bindEvents() {
    this._onTouchStartBound = this._onTouchStart.bind(this);
    this._onTouchMoveBound  = this._onTouchMove.bind(this);
    this._onTouchEndBound   = this._onTouchEnd.bind(this);

    wx.onTouchStart(this._onTouchStartBound);
    wx.onTouchMove(this._onTouchMoveBound);
    wx.onTouchEnd(this._onTouchEndBound);
  }

  destroy() {
    wx.offTouchStart(this._onTouchStartBound);
    wx.offTouchMove(this._onTouchMoveBound);
    wx.offTouchEnd(this._onTouchEndBound);
  }

  // ─── 角度计算 ─────────────────────────────────────────────

  _calcAngle(touchX, touchY) {
    const dx = touchX - this.x;
    const dy = -(touchY - this.y);
    let angle = Math.atan2(dy, dx);
    if (angle < 0) {
      angle = dx < 0 ? MAX_ANGLE : MIN_ANGLE;
    }
    return Math.min(MAX_ANGLE, Math.max(MIN_ANGLE, angle));
  }

  // ─── 瞄准线计算 ───────────────────────────────────────────

  _calcAimPoints(angle) {
    const R = BUBBLE_RADIUS;
    const points = [{ x: this.x, y: this.y }];
    let cx = this.x;
    let cy = this.y;
    let vx = Math.cos(angle);
    let vy = -Math.sin(angle);

    for (let i = 0; i < 6; i++) {
      const tLeft  = vx < 0 ? (R - cx) / vx         : Infinity;
      const tRight = vx > 0 ? (SCREEN_WIDTH - R - cx) / vx : Infinity;
      const tTop   = vy < 0 ? (R - cy) / vy          : Infinity;
      const t = Math.min(tLeft, tRight, tTop);
      if (!isFinite(t) || t <= 0) break;
      cx += vx * t;
      cy += vy * t;
      points.push({ x: cx, y: cy });
      if (t === tTop) break;
      vx = -vx;
    }
    return points;
  }

  // ─── 触摸回调 ─────────────────────────────────────────────

  _onTouchStart(e) {
    if (GameGlobal.databus.isGameOver) return;
    const touch = e.touches[0];
    this._isAiming   = true;
    this._aimAngle   = this._calcAngle(touch.clientX, touch.clientY);
    this._aimPoints  = this._calcAimPoints(this._aimAngle);
  }

  _onTouchMove(e) {
    if (!this._isAiming || GameGlobal.databus.isGameOver) return;
    const touch = e.changedTouches ? e.changedTouches[0] : e.touches[0];
    this._aimAngle  = this._calcAngle(touch.clientX, touch.clientY);
    this._aimPoints = this._calcAimPoints(this._aimAngle);
  }

  _onTouchEnd() {
    if (!this._isAiming || GameGlobal.databus.isGameOver) return;
    this._isAiming  = false;
    this._aimPoints = [];
    this._fire();
  }

  // ─── 发射 ─────────────────────────────────────────────────

  _fire() {
    if (GameGlobal.databus.fireBubbles.some(fb => fb.active)) return;

    const vx = Math.cos(this._aimAngle) * FIRE_SPEED;
    const vy = -Math.sin(this._aimAngle) * FIRE_SPEED;

    // 从鸡头顶位置发射
    const bobOffset = Math.sin(this._bobPhase) * BOB_AMOUNT;
    const bottomY = this._chickenBottom + this._bounceOffsetY + bobOffset;
    const lean = this._currentLean;
    const fireX = this.x + Math.sin(lean) * CHICKEN_HEIGHT * this._bounceScaleY;
    const fireY = bottomY - Math.cos(lean) * CHICKEN_HEIGHT * this._bounceScaleY - BUBBLE_TOP_OFFSET;

    const fb = new FireBubble(fireX, fireY, vx, vy, this.currentColor);
    GameGlobal.databus.fireBubbles.push(fb);
    if (GameGlobal.musicManager && typeof GameGlobal.musicManager.playShoot === 'function') {
      GameGlobal.musicManager.playShoot();
    }
    this.advance();

    this._bounceFrame = 0;
  }

  // ─── 每帧更新 ─────────────────────────────────────────────

  update() {
    // 计算目标倾斜角度：瞄准角度 90°=正上方→lean=0，偏左→lean为负，偏右→lean为正
    let targetLean = 0;
    if (this._isAiming) {
      // aimAngle: MIN_ANGLE(右极限)~PI/2(正上)~MAX_ANGLE(左极限)
      // 映射到 lean: +MAX_LEAN(右倾)~0(正中)~-MAX_LEAN(左倾)
      const normalized = (this._aimAngle - Math.PI / 2) / (MAX_ANGLE - Math.PI / 2);
      // normalized: 0=正上, 1=左极限, 负值=右
      targetLean = -normalized * MAX_LEAN_ANGLE;
    }
    // 平滑插值到目标角度
    this._currentLean += (targetLean - this._currentLean) * LEAN_LERP;

    // 上下呼吸浮动
    this._bobPhase += BOB_SPEED;
    if (this._bobPhase > Math.PI * 2) this._bobPhase -= Math.PI * 2;

    // 发射弹跳动画
    if (this._bounceFrame >= 0) {
      this._updateBounce();
    }
  }

  _updateBounce() {
    const f = this._bounceFrame;
    const totalDuration = SQUASH_DURATION + STRETCH_DURATION + RECOVER_DURATION;

    if (f < SQUASH_DURATION) {
      const t = easeInCubic(f / SQUASH_DURATION);
      this._bounceScaleX = 1 + (SQUASH_SCALE_X - 1) * t;
      this._bounceScaleY = 1 + (SQUASH_SCALE_Y - 1) * t;
    } else if (f < SQUASH_DURATION + STRETCH_DURATION) {
      const t = easeOutCubic((f - SQUASH_DURATION) / STRETCH_DURATION);
      this._bounceScaleX = SQUASH_SCALE_X + (STRETCH_SCALE_X - SQUASH_SCALE_X) * t;
      this._bounceScaleY = SQUASH_SCALE_Y + (STRETCH_SCALE_Y - SQUASH_SCALE_Y) * t;
    } else if (f < totalDuration) {
      const t = easeOutCubic((f - SQUASH_DURATION - STRETCH_DURATION) / RECOVER_DURATION);
      this._bounceScaleX = STRETCH_SCALE_X + (1 - STRETCH_SCALE_X) * t;
      this._bounceScaleY = STRETCH_SCALE_Y + (1 - STRETCH_SCALE_Y) * t;
    } else {
      this._bounceScaleX = 1;
      this._bounceScaleY = 1;
      this._bounceFrame = -1;
      return;
    }

    this._bounceOffsetY = (1 - this._bounceScaleY) * CHICKEN_HEIGHT / 2;
    this._bounceFrame++;
  }

  // ─── 绘制 ─────────────────────────────────────────────────

  _drawAimLine(ctx) {
    this._drawAimLineFrom(ctx, this.x, this.y);
  }

  /**
   * 从指定坐标（泡泡中心）绘制瞄准线
   */
  _drawAimLineFrom(ctx, fromX, fromY) {
    if (!this._isAiming || !this._aimAngle) return;

    // 用实际泡泡位置重新计算瞄准线路径
    const R = BUBBLE_RADIUS;
    const points = [{ x: fromX, y: fromY }];
    let cx = fromX, cy = fromY;
    let vx = Math.cos(this._aimAngle);
    let vy = -Math.sin(this._aimAngle);

    for (let i = 0; i < 6; i++) {
      const tLeft  = vx < 0 ? (R - cx) / vx         : Infinity;
      const tRight = vx > 0 ? (SCREEN_WIDTH - R - cx) / vx : Infinity;
      const tTop   = vy < 0 ? (R - cy) / vy          : Infinity;
      const t = Math.min(tLeft, tRight, tTop);
      if (!isFinite(t) || t <= 0) break;
      cx += vx * t;
      cy += vy * t;
      points.push({ x: cx, y: cy });
      if (t === tTop) break;
      vx = -vx;
    }

    if (points.length < 2) return;

    ctx.save();
    ctx.setLineDash([6, 7]);
    ctx.strokeStyle = 'rgba(255,255,255,0.65)';
    ctx.lineWidth   = 2;
    ctx.lineJoin    = 'round';

    ctx.beginPath();
    ctx.moveTo(points[0].x, points[0].y);
    for (let i = 1; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y);
    }
    ctx.stroke();
    ctx.setLineDash([]);
    ctx.restore();
  }

  /**
   * 绘制鸡：身体朝向跟随瞄准方向倾斜，以底部中心为旋转轴。
   */
  _drawChicken(ctx) {
    const cx = this.x;
    const bobOffset = Math.sin(this._bobPhase) * BOB_AMOUNT;
    const bottomY = this._chickenBottom + this._bounceOffsetY + bobOffset;

    ctx.save();
    ctx.translate(cx, bottomY);
    ctx.rotate(this._currentLean);
    ctx.scale(this._bounceScaleX, this._bounceScaleY);
    ctx.drawImage(_chickenImg, -CHICKEN_WIDTH / 2, -CHICKEN_HEIGHT, CHICKEN_WIDTH, CHICKEN_HEIGHT);
    ctx.restore();
  }

  render(ctx) {
    const R = BUBBLE_RADIUS;

    this.update();

    // 先算出泡泡实际位置（鸡头顶，跟随倾斜）
    const bobOffset = Math.sin(this._bobPhase) * BOB_AMOUNT;
    const bottomY = this._chickenBottom + this._bounceOffsetY + bobOffset;
    const lean = this._currentLean;
    const headX = this.x + Math.sin(lean) * CHICKEN_HEIGHT * this._bounceScaleY;
    const headY = bottomY - Math.cos(lean) * CHICKEN_HEIGHT * this._bounceScaleY - BUBBLE_TOP_OFFSET;

    // 瞄准线从泡泡中心发出（而非固定屏幕中心）
    this._drawAimLineFrom(ctx, headX, headY);
    this._drawChicken(ctx);

    // 绘制当前待射泡泡
    drawBubble3D(ctx, headX, headY, R, this.currentColor);

    // 下一颗预览泡泡
    const nextR = R * NEXT_SCALE;
    const nextX = this.x + NEXT_X_OFFSET;
    const nextY = this._chickenBottom + NEXT_Y_OFFSET;
    drawBubble3D(ctx, nextX, nextY, nextR, this.nextColor);

    ctx.save();
    ctx.fillStyle     = 'rgba(255,255,255,0.65)';
    ctx.font          = `bold ${Math.round(R * 0.6)}px Arial`;
    ctx.textAlign     = 'center';
    ctx.textBaseline  = 'bottom';
    ctx.fillText('下一个', nextX, nextY - nextR - 2);
    ctx.restore();
  }
}
