// 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 SampleProfileLoadingProgressEvent
    implements M.SampleProfileLoadingProgressEvent {
  final SampleProfileLoadingProgress progress;
  SampleProfileLoadingProgressEvent(this.progress);
}

class SampleProfileLoadingProgress extends M.SampleProfileLoadingProgress {
  StreamController<SampleProfileLoadingProgressEvent> _onProgress =
      StreamController<SampleProfileLoadingProgressEvent>.broadcast();
  Stream<SampleProfileLoadingProgressEvent> get onProgress =>
      _onProgress.stream;

  final S.ServiceObjectOwner owner;
  final S.Class? cls;
  final M.SampleProfileTag tag;
  final bool clear;
  final M.SampleProfileType type;

  M.SampleProfileLoadingStatus _status = M.SampleProfileLoadingStatus.fetching;
  double _progress = 0.0;
  final _fetchingTime = Stopwatch();
  final _loadingTime = Stopwatch();
  SampleProfile? _profile;

  M.SampleProfileLoadingStatus get status => _status;
  double get progress => _progress;
  Duration get fetchingTime => _fetchingTime.elapsed;
  Duration get loadingTime => _loadingTime.elapsed;
  SampleProfile get profile => _profile!;

  SampleProfileLoadingProgress(this.owner, this.tag, this.clear,
      {this.type: M.SampleProfileType.cpu, this.cls}) {
    _run();
  }

  Future _run() async {
    _fetchingTime.start();
    try {
      if (clear && (type == M.SampleProfileType.cpu)) {
        await owner.invokeRpc('clearCpuSamples', {});
      }

      var response;
      if (type == M.SampleProfileType.cpu) {
        response = cls != null
            ? await cls!.getAllocationTraces()
            : await owner.invokeRpc('getCpuSamples', {'_code': true});
      } else if (type == M.SampleProfileType.memory) {
        assert(owner is M.VM);
        response = await owner
            .invokeRpc('_getNativeAllocationSamples', {'_code': true});
      } else {
        throw Exception('Unknown M.SampleProfileType: $type');
      }

      _fetchingTime.stop();
      _loadingTime.start();
      _status = M.SampleProfileLoadingStatus.loading;
      _triggerOnProgress();

      SampleProfile profile = SampleProfile();
      Stream<double> progress =
          profile.loadProgress(owner, response as S.ServiceMap);
      progress.listen((value) {
        _progress = value;
        _triggerOnProgress();
      });

      await progress.drain();

      profile.tagOrder = tag;
      profile.buildFunctionCallerAndCallees();
      _profile = profile;

      _loadingTime.stop();
      _status = M.SampleProfileLoadingStatus.loaded;
      _triggerOnProgress();
    } catch (e) {
      if (e is S.ServerRpcException) {
        if (e.code == S.ServerRpcException.kFeatureDisabled) {
          _status = M.SampleProfileLoadingStatus.disabled;
          _triggerOnProgress();
        }
      }
      rethrow;
    } finally {
      _onProgress.close();
    }
  }

  void _triggerOnProgress() {
    _onProgress.add(SampleProfileLoadingProgressEvent(this));
  }

  void reuse(M.SampleProfileTag t) {
    _profile!.tagOrder = t;
    final onProgress =
        StreamController<SampleProfileLoadingProgressEvent>.broadcast();
    Timer.run(() {
      onProgress.add(SampleProfileLoadingProgressEvent(this));
      onProgress.close();
    });
    _onProgress = onProgress;
  }
}

class IsolateSampleProfileRepository
    implements M.IsolateSampleProfileRepository {
  SampleProfileLoadingProgress? _last;

  Stream<SampleProfileLoadingProgressEvent> get(
      M.IsolateRef i, M.SampleProfileTag t,
      {bool clear: false, bool forceFetch: false}) {
    assert(clear != null);
    assert(forceFetch != null);
    S.Isolate isolate = i as S.Isolate;
    assert(isolate != null);
    if ((_last != null) && !clear && !forceFetch && (_last!.owner == isolate)) {
      _last!.reuse(t);
    } else {
      _last = SampleProfileLoadingProgress(isolate, t, clear);
    }
    return _last!.onProgress;
  }
}

class ClassSampleProfileRepository implements M.ClassSampleProfileRepository {
  Stream<SampleProfileLoadingProgressEvent> get(
      covariant M.Isolate i, M.ClassRef c, M.SampleProfileTag t,
      {bool clear: false, bool forceFetch: false}) {
    S.Isolate isolate = i as S.Isolate;
    S.Class cls = c as S.Class;
    assert(isolate != null);
    assert(cls != null);
    return SampleProfileLoadingProgress(isolate, t, false, cls: cls).onProgress;
  }

  Future enable(M.IsolateRef i, M.ClassRef c) {
    S.Class cls = c as S.Class;
    assert(cls != null);
    return cls.setTraceAllocations(true);
  }

  Future disable(M.IsolateRef i, M.ClassRef c) {
    S.Class cls = c as S.Class;
    assert(cls != null);
    return cls.setTraceAllocations(false);
  }
}

class NativeMemorySampleProfileRepository
    implements M.NativeMemorySampleProfileRepository {
  SampleProfileLoadingProgress? _last;

  Stream<SampleProfileLoadingProgressEvent> get(M.VM vm, M.SampleProfileTag t,
      {bool forceFetch: false, bool clear: false}) {
    assert(forceFetch != null);
    S.VM owner = vm as S.VM;
    assert(owner != null);

    if ((_last != null) && (_last!.profile != null) && !forceFetch) {
      _last!.reuse(t);
    } else {
      _last = SampleProfileLoadingProgress(owner, t, false,
          type: M.SampleProfileType.memory);
    }
    return _last!.onProgress;
  }
}
