// 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.

// @dart = 2.7

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

library output_collector;

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

class BufferedOutputSink implements api.OutputSink {
  StringBuffer sb = new 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 write(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) {
    sinks.forEach((api.OutputSink sink) => sink.add(event));
  }

  @override
  void close() {
    sinks.forEach((api.OutputSink sink) => 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, () => new 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 (api.OutputType type in outputMap.keys) {
      for (String name in outputMap[type].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, () => new 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;
  }
}
