/**
 * PlayerTank.js
 * Player-controlled tank with fire level, lives, shield, and respawn logic.
 */

const Tank = require('./Tank');
const {
  TANK_TYPE,
  TANK_CONFIG,
  FIRE_LEVEL,
  MAX_BULLETS_BY_LEVEL,
  DIRECTION,
  DEFAULT_LIVES,
  SHIELD_DURATION,
  INVINCIBLE_BLINK_INTERVAL,
  TILE_SIZE,
  MAP_OFFSET_X,
  MAP_OFFSET_Y,
} = require('../base/GameGlobal');

class PlayerTank extends Tank {
  /**
   * @param {object} params
   * @param {number} params.col - Spawn grid column.
   * @param {number} params.row - Spawn grid row.
   */
  constructor(params) {
    const cfg = TANK_CONFIG[TANK_TYPE.PLAYER];
    const spawnX = MAP_OFFSET_X + params.col * TILE_SIZE + TILE_SIZE / 2;
    const spawnY = MAP_OFFSET_Y + params.row * TILE_SIZE + TILE_SIZE / 2;

    super({
      x: spawnX,
      y: spawnY,
      speed: cfg.speed,
      hp: cfg.hp,
      color: cfg.color,
      size: cfg.size,
      direction: DIRECTION.UP,
    });

    this.type = TANK_TYPE.PLAYER;
    this.spawnCol = params.col;
    this.spawnRow = params.row;

    // Skin colors (reserved for future use)
    this._skinColors = null;
    this._skinId = null;

    // Fire level system
    this.fireLevel = FIRE_LEVEL.LV1;

    // Lives
    this.lives = DEFAULT_LIVES;

    // Shield (invincibility)
    this._shieldTimer = 0; // ms remaining
    this._shieldBlink = false;
    this._blinkTimer = 0;

    // Active bullets count (managed externally)
    this.activeBullets = 0;

    // Respawn invincibility (short shield on spawn)
    this._respawnShieldDuration = 3000; // 3 seconds on respawn
  }

  /**
   * Update player tank state.
   * @param {number} dt - Delta time in seconds.
   */
  update(dt) {
    if (!this.alive) return;

    // Shield timer
    if (this._shieldTimer > 0) {
      this._shieldTimer -= dt * 1000;
      this._blinkTimer += dt * 1000;

      if (this._blinkTimer >= INVINCIBLE_BLINK_INTERVAL) {
        this._blinkTimer = 0;
        this._shieldBlink = !this._shieldBlink;
      }

      if (this._shieldTimer <= 0) {
        this._shieldTimer = 0;
        this._shieldBlink = false;
      }
    }
  }

  /**
   * Override takeDamage to check shield.
   * @param {number} amount
   * @returns {boolean} Whether destroyed.
   */
  takeDamage(amount = 1) {
    if (this._shieldTimer > 0) return false; // invincible
    return super.takeDamage(amount);
  }

  /**
   * Handle player death: lose a life and respawn, or game over.
   * @returns {boolean} True if player has lives remaining and respawned.
   */
  die() {
    this.alive = false;
    this.lives--;

    if (this.lives > 0) {
      this.respawn();
      return true;
    }
    return false; // game over
  }

  /**
   * Respawn at the spawn point with temporary invincibility.
   */
  respawn() {
    this.x = MAP_OFFSET_X + this.spawnCol * TILE_SIZE + TILE_SIZE / 2;
    this.y = MAP_OFFSET_Y + this.spawnRow * TILE_SIZE + TILE_SIZE / 2;
    this.direction = DIRECTION.UP;
    this.hp = 1;
    this.alive = true;
    this.visible = true;
    this.fireLevel = FIRE_LEVEL.LV1;
    this.activeBullets = 0;

    // Temporary shield on respawn
    this.activateShield(this._respawnShieldDuration);
  }

  /**
   * Activate shield (invincibility).
   * @param {number} duration - Duration in ms.
   */
  activateShield(duration) {
    this._shieldTimer = duration;
    this._blinkTimer = 0;
    this._shieldBlink = false;
  }

  /**
   * Upgrade fire level.
   */
  upgradeFireLevel() {
    if (this.fireLevel < FIRE_LEVEL.LV3) {
      this.fireLevel++;
    }
  }

  /**
   * Add a life.
   */
  addLife() {
    this.lives++;
  }

  /**
   * Check if the player can fire (based on active bullets and fire level).
   * @returns {boolean}
   */
  canFire() {
    return this.alive && this.activeBullets < MAX_BULLETS_BY_LEVEL[this.fireLevel];
  }

  /**
   * Whether the bullet should break steel.
   * @returns {boolean}
   */
  canBreakSteel() {
    return this.fireLevel >= FIRE_LEVEL.LV3;
  }

  /**
   * Render player tank with shield effect.
   * @param {CanvasRenderingContext2D} ctx
   */
  render(ctx) {
    if (!this.alive) return;

    // Call base render
    super.render(ctx);

    // Draw shield effect
    if (this._shieldTimer > 0 && this._shieldBlink) {
      ctx.save();
      ctx.strokeStyle = '#00FFFF';
      ctx.lineWidth = 2;
      ctx.globalAlpha = 0.6;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.halfSize + 4, 0, Math.PI * 2);
      ctx.stroke();
      ctx.restore();
    }
  }

  /** Whether the player is currently shielded. */
  get isShielded() {
    return this._shieldTimer > 0;
  }

  /** Get max bullets allowed on screen. */
  get maxBullets() {
    return MAX_BULLETS_BY_LEVEL[this.fireLevel];
  }
}

module.exports = PlayerTank;
