import 'package:flutter/material.dart';
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
import 'package:wolf_3d_renderer/base_renderer.dart';

class WolfAsciiRenderer extends BaseWolfRenderer {
  const WolfAsciiRenderer({
    required super.engine,
    super.key,
  });

  @override
  State<WolfAsciiRenderer> createState() => _WolfAsciiRendererState();
}

class _WolfAsciiRendererState extends BaseWolfRendererState<WolfAsciiRenderer> {
  List<List<ColoredChar>> _asciiFrame = [];
  final AsciiRasterizer _asciiRasterizer = AsciiRasterizer();

  @override
  Color get scaffoldColor => const Color.fromARGB(255, 4, 64, 64);

  @override
  void performRender() {
    setState(() {
      _asciiFrame = _asciiRasterizer.render(
        widget.engine,
        FrameBuffer(160, 100),
      );
    });
  }

  @override
  Widget buildViewport(BuildContext context) {
    return _asciiFrame.isEmpty
        ? const SizedBox.shrink()
        : AsciiFrameWidget(frameData: _asciiFrame);
  }
}

class AsciiFrameWidget extends StatelessWidget {
  final List<List<ColoredChar>> frameData;

  const AsciiFrameWidget({super.key, required this.frameData});

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: 4 / 3,
      child: FittedBox(
        fit: BoxFit.fill,
        child: Container(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: frameData.map((row) {
              List<TextSpan> optimizedSpans = [];
              if (row.isNotEmpty) {
                Color currentColor = Color(row[0].argb);
                StringBuffer currentSegment = StringBuffer(row[0].char);

                for (int i = 1; i < row.length; i++) {
                  if (Color(row[i].argb) == currentColor) {
                    currentSegment.write(row[i].char);
                  } else {
                    optimizedSpans.add(
                      TextSpan(
                        text: currentSegment.toString(),
                        style: TextStyle(color: currentColor),
                      ),
                    );
                    currentColor = Color(row[i].argb);
                    currentSegment = StringBuffer(row[i].char);
                  }
                }
                optimizedSpans.add(
                  TextSpan(
                    text: currentSegment.toString(),
                    style: TextStyle(color: currentColor),
                  ),
                );
              }

              return RichText(
                text: TextSpan(
                  style: const TextStyle(fontFamily: 'monospace', height: 1.0),
                  children: optimizedSpans,
                ),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}
