// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Output provider that collects the output in string buffers.

library;

import 'package:compiler/compiler_api.dart' as api;

class BufferedOutputSink implements api.OutputSink {
  StringBuffer? sb = StringBuffer();
  String? text;

  @override
  void add(String event) {
    sb!.write(event);
  }

  @override
  void close() {
    text = sb.toString();
    sb = null;
  }

  @override
  String toString() {
    return text ?? sb.toString();
  }
}

class BufferedBinaryOutputSink implements api.BinaryOutputSink {
  final Uri uri;

  List<int> list = <int>[];

  BufferedBinaryOutputSink(this.uri);

  @override
  void add(List<int> buffer, [int start = 0, int? end]) {
    list.addAll(buffer.sublist(start, end));
  }

  @override
  void close() {}

  @override
  String toString() {
    return 'BufferedBinaryOutputSink($uri)';
  }
}

class CloningOutputSink implements api.OutputSink {
  final List<api.OutputSink> sinks;

  CloningOutputSink(this.sinks);

  @override
  void add(String event) {
    for (var sink in sinks) {
      sink.add(event);
    }
  }

  @override
  void close() {
    for (var sink in sinks) {
      sink.close();
    }
  }
}

class OutputCollector implements api.CompilerOutput {
  Map<api.OutputType, Map<String, BufferedOutputSink>> outputMap = {};
  Map<Uri, BufferedBinaryOutputSink> binaryOutputMap = {};

  String? getOutput(String name, api.OutputType type) {
    Map<String, BufferedOutputSink>? sinkMap = outputMap[type];
    if (sinkMap == null) {
      print("No output available for $type.");
      return null;
    }
    BufferedOutputSink? sink = sinkMap[name];
    if (sink == null) {
      print("Output '$name' not found for $type. Available: ${sinkMap.keys}");
      return null;
    } else {
      return sink.text;
    }
  }

  @override
  api.BinaryOutputSink createBinarySink(Uri uri) {
    return binaryOutputMap.putIfAbsent(
      uri,
      () => BufferedBinaryOutputSink(uri),
    );
  }

  /// `true` if any output has been collected.
  bool get hasOutput => outputMap.isNotEmpty || binaryOutputMap.isNotEmpty;

  /// `true` if any output other than main output has been collected.
  bool get hasExtraOutput {
    for (Map<String, BufferedOutputSink> output in outputMap.values) {
      for (String name in output.keys) {
        if (name != '') return true;
      }
    }
    return binaryOutputMap.isNotEmpty;
  }

  @override
  api.OutputSink createOutputSink(
    String name,
    String extension,
    api.OutputType type,
  ) {
    Map<String, BufferedOutputSink> sinkMap = outputMap.putIfAbsent(
      type,
      () => {},
    );
    return sinkMap.putIfAbsent(name, () => BufferedOutputSink());
  }

  Map<api.OutputType, Map<String, String>> clear() {
    Map<api.OutputType, Map<String, String>> outputMapResult = {};
    outputMap.forEach((
      api.OutputType outputType,
      Map<String, BufferedOutputSink> sinkMap,
    ) {
      Map<String, String> sinkMapResult = outputMapResult[outputType] = {};
      sinkMap.forEach((String name, BufferedOutputSink sink) {
        sinkMapResult[name] = sink.toString();
      });
    });
    outputMap.clear();
    binaryOutputMap.clear();
    return outputMapResult;
  }
}
