import 'package:asciineverdie/src/shared/animation/background_data.dart';
import 'package:asciineverdie/src/shared/animation/background_layer.dart';
import 'package:asciineverdie/src/shared/animation/canvas/ascii_cell.dart';
import 'package:asciineverdie/src/shared/animation/canvas/ascii_layer.dart';
import 'package:asciineverdie/src/shared/animation/race_character_frames.dart';

/// Canvas용 걷기 애니메이션 합성기
///
/// 배경 스크롤 + 걷는 캐릭터
/// Phase 4: 종족별 캐릭터 프레임 지원
class CanvasWalkingComposer {
  const CanvasWalkingComposer({this.raceId});

  /// 종족 ID (종족별 캐릭터 프레임 선택용)
  final String? raceId;

  /// 프레임 상수
  static const int frameWidth = 60;
  static const int frameHeight = 8;

  /// 레이어 기반 프레임 생성
  List<AsciiLayer> composeLayers(int globalTick) {
    return [
      _createBackgroundLayer(globalTick),
      _createCharacterLayer(globalTick),
    ];
  }

  /// 배경 레이어 생성 (z=0) - 숲 환경 기본
  AsciiLayer _createBackgroundLayer(int globalTick) {
    final cells = List.generate(
      frameHeight,
      (_) => List.filled(frameWidth, AsciiCell.empty),
    );

    final bgLayers = getBackgroundLayers(EnvironmentType.forest);
    for (final layer in bgLayers) {
      // 스크롤 오프셋 계산 (걷기는 더 빠른 스크롤)
      final offset = (globalTick * layer.scrollSpeed * 2).toInt();

      for (var i = 0; i < layer.lines.length; i++) {
        final y = layer.yStart + i;
        if (y >= frameHeight) break;

        final pattern = layer.lines[i];
        if (pattern.isEmpty) continue;

        for (var x = 0; x < frameWidth; x++) {
          final patternIdx = (x + offset) % pattern.length;
          final char = pattern[patternIdx];
          if (char != ' ') {
            cells[y][x] = AsciiCell.fromChar(char);
          }
        }
      }
    }

    return AsciiLayer(cells: cells, zIndex: 0);
  }

  /// 걷는 캐릭터 레이어 생성 (z=1)
  /// Phase 4: 종족별 프레임 지원
  AsciiLayer _createCharacterLayer(int globalTick) {
    final frameIndex = globalTick % 4; // 4프레임 루프
    List<String> charFrame;

    // 종족별 프레임 사용 시도
    if (raceId != null && raceId!.isNotEmpty) {
      final raceData = RaceCharacterFrames.get(raceId!);
      if (raceData != null) {
        // idle 프레임을 기반으로 걷기 애니메이션 생성
        final idleFrame = raceData.idle[frameIndex % raceData.idle.length];
        charFrame = _animateWalking(idleFrame.lines, frameIndex);
      } else {
        charFrame = _walkingFrames[frameIndex];
      }
    } else {
      charFrame = _walkingFrames[frameIndex];
    }

    final cells = _spriteToCells(charFrame);

    // 화면 중앙에 캐릭터 배치 (25% 위치)
    const charX = 15;
    // 바닥 레이어(Y=7) 위에 서있도록
    final charY = frameHeight - cells.length - 1;

    return AsciiLayer(cells: cells, zIndex: 1, offsetX: charX, offsetY: charY);
  }

  /// idle 프레임 기반 걷기 애니메이션 생성
  /// 종족별 다리 모양을 유지 (idle 프레임이 4개라 자연스럽게 변화)
  List<String> _animateWalking(List<String> idleLines, int frameIndex) {
    // idle 프레임을 그대로 사용 (종족별 다리 모양 유지)
    // frameIndex에 따라 idle[0~3] 중 하나가 선택되어 자연스럽게 애니메이션됨
    return idleLines;
  }

  /// 문자열 스프라이트를 AsciiCell 2D 배열로 변환
  List<List<AsciiCell>> _spriteToCells(List<String> lines) {
    return lines.map((line) {
      return line.split('').map(AsciiCell.fromChar).toList();
    }).toList();
  }
}

// ============================================================================
// 걷기 프레임 (4프레임 루프)
// ============================================================================

const _walkingFrames = [
  // 프레임 1: 오른발 앞
  [r'  o   ', r' /|\  ', r' /|   '],
  // 프레임 2: 모음
  [r'  o   ', r' /|\  ', r'  |\  '],
  // 프레임 3: 왼발 앞
  [r'  o   ', r' /|\  ', r' /|   '],
  // 프레임 4: 모음
  [r'  o   ', r' /|\  ', r'  |\  '],
];
