// Copyright (c) 2016, 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

part of repositories;

class Metric implements M.Metric {
  final String id;
  String get name => internal.name;
  String get description => internal.description;
  final internal;

  Metric(this.id, this.internal);
}

class MetricSample implements M.MetricSample {
  final double value;
  final DateTime time = new DateTime.now();
  MetricSample(this.value);
}

class MetricRepository implements M.MetricRepository {
  final Map<S.Isolate, Map<Metric, List<M.MetricSample>>> _samples =
      <S.Isolate, Map<Metric, List<M.MetricSample>>>{};
  final Map<S.Isolate, Map<Metric, int>> _rates =
      <S.Isolate, Map<Metric, int>>{};
  final Map<S.Isolate, Map<Metric, int>> _sizes =
      <S.Isolate, Map<Metric, int>>{};
  Timer? _timer;
  int count = 0;

  Future<Iterable<Metric>> list(M.IsolateRef i) async {
    S.Isolate isolate = i as S.Isolate;
    assert(isolate != null);
    if (_samples.containsKey(isolate)) {
      return _samples[isolate]!.keys;
    }
    return const [];
  }

  Future startSampling(M.IsolateRef i) async {
    S.Isolate isolate = i as S.Isolate;
    assert(isolate != null);
    if (!_samples.containsKey(isolate)) {
      await isolate.refreshMetrics();
      final samples = _samples[isolate] = <Metric, List<M.MetricSample>>{};
      final rates = _rates[isolate] = <Metric, int>{};
      final sizes = _sizes[isolate] = <Metric, int>{};
      final metrics = []
        ..addAll(isolate.dartMetrics.keys
            .map((name) => new Metric(name, isolate.dartMetrics[name]))
            .toList())
        ..addAll(isolate.nativeMetrics.keys
            .map((name) => new Metric(name, isolate.nativeMetrics[name]))
            .toList());
      for (final metric in metrics) {
        samples[metric] = [new MetricSample(metric.internal.value)];
        rates[metric] = _rateToInteger(M.MetricSamplingRate.off);
        sizes[metric] = _sizeToInteger(M.MetricBufferSize.n100samples);
      }
      if (_samples.length == 1) {
        count = 0;
        _timer = new Timer.periodic(new Duration(milliseconds: 100), _update);
      }
    }
  }

  Future stopSampling(M.IsolateRef isolate) async {
    if (_samples.containsKey(isolate)) {
      _samples.remove(isolate);
      _rates.remove(isolate);
      _sizes.remove(isolate);
      if (_samples.isEmpty) {
        _timer!.cancel();
      }
    }
  }

  M.MetricSamplingRate getSamplingRate(M.IsolateRef i, M.Metric m) {
    if (_rates.containsKey(i)) {
      final metrics = _rates[i]!;
      if (metrics.containsKey(m)) {
        switch (metrics[m]) {
          case 0:
            return M.MetricSamplingRate.off;
          case 1:
            return M.MetricSamplingRate.e100ms;
          case 10:
            return M.MetricSamplingRate.e1s;
          case 20:
            return M.MetricSamplingRate.e2s;
          case 40:
            return M.MetricSamplingRate.e4s;
          case 80:
            return M.MetricSamplingRate.e8s;
        }
      }
    }
    throw new Exception('Sampling for isolate ${i.id} is not started');
  }

  void setSamplingRate(M.IsolateRef i, M.Metric m, M.MetricSamplingRate r) {
    if (_rates.containsKey(i)) {
      final metrics = _rates[i]!;
      if (metrics.containsKey(m)) {
        metrics[m as Metric] = _rateToInteger(r);
      }
    } else {
      throw new Exception('Sampling for isolate ${i.id} is not started');
    }
  }

  M.MetricBufferSize getBufferSize(M.IsolateRef i, M.Metric m) {
    if (_sizes.containsKey(i)) {
      final metrics = _sizes[i]!;
      if (metrics.containsKey(m)) {
        switch (metrics[m]) {
          case 10:
            return M.MetricBufferSize.n10samples;
          case 100:
            return M.MetricBufferSize.n100samples;
          case 1000:
            return M.MetricBufferSize.n1000samples;
        }
      }
    }
    throw new Exception('Sampling for isolate ${i.id} is not started');
  }

  void setBufferSize(M.IsolateRef i, M.Metric m, M.MetricBufferSize s) {
    if (_sizes.containsKey(i)) {
      final metrics = _sizes[i]!;
      if (metrics.containsKey(m)) {
        metrics[m as Metric] = _sizeToInteger(s);
      }
    } else {
      throw new Exception('Sampling for isolate ${i.id} is not started');
    }
  }

  static int _rateToInteger(M.MetricSamplingRate r) {
    switch (r) {
      case M.MetricSamplingRate.off:
        return 0;
      case M.MetricSamplingRate.e100ms:
        return 1;
      case M.MetricSamplingRate.e1s:
        return 10;
      case M.MetricSamplingRate.e2s:
        return 20;
      case M.MetricSamplingRate.e4s:
        return 40;
      case M.MetricSamplingRate.e8s:
        return 80;
    }
    throw new Exception('Unknown MetricSamplingRate ($r)');
  }

  static int _sizeToInteger(M.MetricBufferSize s) {
    switch (s) {
      case M.MetricBufferSize.n10samples:
        return 10;
      case M.MetricBufferSize.n100samples:
        return 100;
      case M.MetricBufferSize.n1000samples:
        return 1000;
    }
    throw new Exception('Unknown MetricBufferSize ($s)');
  }

  Iterable<M.MetricSample>? getSamples(M.IsolateRef i, M.Metric m) {
    if (_samples.containsKey(i)) {
      final metrics = _samples[i]!;
      if (metrics.containsKey(m)) {
        return metrics[m];
      }
    }
    return null;
  }

  double getMinValue(M.IsolateRef i, M.Metric m) {
    Metric metric = m as Metric;
    assert(metric != null);
    return metric.internal.min;
  }

  double getMaxValue(M.IsolateRef i, M.Metric m) {
    Metric metric = m as Metric;
    assert(metric != null);
    return metric.internal.max;
  }

  void _update(_) {
    for (final isolate in _rates.keys) {
      final metrics = _rates[isolate]!;
      for (final metric in metrics.keys) {
        final rate = metrics[metric]!;
        if (rate != 0 && count % rate == 0) {
          final size = _sizes[isolate]![metric]!;
          final samples = _samples[isolate]![metric]!;
          metric.internal.reload().then((m) {
            if (samples.length >= size) {
              samples.removeRange(0, samples.length - size + 1);
            }
            samples.add(new MetricSample(m.value));
          });
        }
      }
    }
    ++count;
  }
}
