// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: avoid_as

import 'dart:async';

import 'package:lib.schemas.dart/entity_codec.dart';
import 'package:lib.app.dart/logging.dart';
import 'package:lib.app_driver.dart/module_driver.dart';
import 'package:lib.module.dart/module.dart';
import 'package:fidl_fuchsia_modular/fidl.dart'
    show SurfaceRelation, SurfaceArrangement, SurfaceDependency;
import 'package:flutter/material.dart';

class FakeIntentParameters implements IntentParameters {
  FakeModuleDriver _driver;

  FakeIntentParameters({
    // TODO: Refactor this class to use the new SDK instead of deprecated API
    // ignore: deprecated_member_use
    ModuleDriver moduleDriver,
  }) {
    _driver = moduleDriver;
  }

  @override
  Future<T> getParameterData<T>(
      String parameterName, EntityCodec<T> codec) async {
    return _driver.getTestLinkCurrentValue(parameterName, codec);
  }

  @override
  Stream<T> watchParameterData<T>(String parameterName, EntityCodec<T> codec) {
    StreamController<T> controller = new StreamController<T>(
      onListen: () {},
      onPause: () {},
      onResume: () {},
      onCancel: () {},
    )
      ..add(_driver.getTestLinkCurrentValue(parameterName, codec))
      ..close();
    return controller.stream;
  }
}

class LinkStreamController {
  final StreamController<String> controller;
  final bool watchAll;

  LinkStreamController({@required this.controller, @required this.watchAll});
}

// TODO: Refactor this class to use the new SDK instead of deprecated API
// ignore: deprecated_member_use
class FakeModuleDriver implements ModuleDriver {
  final _linkValue = {};
  final _linkStreamControllers = {};
  final _startModuleIntents = [];
  final _fakeModuleContext = FakeModuleContext();
  final _fakeModuleControllerClient = FakeModuleControllerClient();
  OnHandleIntent _onHandleIntent;
  FakeIntentParameters _parameters;

  @override
  // ignore: use_to_and_as_if_applicable, deprecated_member_use
  Future<ModuleDriver> start() {
    return Future.value(this);
  }

  @override
  set onHandleIntent(OnHandleIntent onHandleIntent) {
    _onHandleIntent = onHandleIntent;
  }

  // Tells the module driver to create fake intent parameters which map to
  // all the values which have been |putTestValue|'d and send it to the module.
  void handleIntent() {
    _parameters = FakeIntentParameters(moduleDriver: this);
    _onHandleIntent('', _parameters);
  }

  // Value is only send to watchers registered with all = true.
  @override
  Future<String> put<T>(String key, T value, EntityCodec<T> codec) async {
    _linkValue[key] = codec.encode(value);
    List<LinkStreamController> streamContollerList =
        _getLinkStreamControllerList(key);
    for (var linkStreamController in streamContollerList) {
      if (linkStreamController.watchAll) {
        /// Encode and decode to tests codec.
        linkStreamController.controller.add(codec.encode(value));
      }
    }
    return null;
  }

  @override
  ModuleContextClient get moduleContext => _fakeModuleContext;

  @override
  Future<T> get<T>(String linkName, EntityCodec<T> codec) async {
    return codec.decode(_linkValue[linkName]);
  }

  @override
  Stream<T> watch<T>(String key, EntityCodec<T> codec, {bool all = false}) {
    // Do not combine the next two lines or dart gets confused about types.
    // ignore: close_sinks
    StreamController streamController = _createNewStreamController(key, all);
    return streamController.stream.map(codec.decode);
  }

  @override
  Future<ModuleControllerClient> startModule(
      {@required Intent intent,
      String name,
      String module,
      SurfaceRelation surfaceRelation = const SurfaceRelation(
        arrangement: SurfaceArrangement.copresent,
        dependency: SurfaceDependency.dependent,
        emphasis: 0.5,
      )}) {
    _startModuleIntents.add(intent);
    return Future.value(_fakeModuleControllerClient);
  }

  /// Puts a value on a link from a test. Value is sent to all watcher of the
  /// link.
  void putTestValue<T>(String key, T value, EntityCodec<T> codec) {
    _linkValue[key] = codec.encode(value);
    List<LinkStreamController> streamContollerList =
        _getLinkStreamControllerList(key);
    for (var linkStreamController in streamContollerList) {
      linkStreamController.controller.add(codec.encode(value));
    }
  }

  /// Returns the most recent value put on a link or null if no value has been
  /// put on the link.
  T getTestLinkCurrentValue<T>(String key, EntityCodec<T> codec) {
    return codec.decode(_linkValue[key]);
  }

  /// Returns a list of intents that have been sent to [startModule].
  List<Intent> getTestStartModuleIntents() {
    return List.unmodifiable(_startModuleIntents);
  }

  void cleanUp() {
    _linkStreamControllers.forEach((_, controllerList) =>
        // ignore: avoid_function_literals_in_foreach_calls
        controllerList.forEach((contoller) => contoller.controller.close()));
  }

  StreamController<String> _createNewStreamController<T>(
      String key, bool watchAll) {
    // Do not combine the lines in this method or dart gets confused about
    // types.
    StreamController<String> newController = StreamController();
    LinkStreamController newLinkController =
        LinkStreamController(controller: newController, watchAll: watchAll);
    List<LinkStreamController> linkStreamControllerList =
        _getLinkStreamControllerList(key);
    // ignore: cascade_invocations
    linkStreamControllerList.add(newLinkController);
    return newController;
  }

  List<LinkStreamController> _getLinkStreamControllerList(String key) {
    // Do not combine the lines in this method or dart gets confused about
    // types.
    if (!_linkStreamControllers.containsKey(key)) {
      // ignore: close_sinks
      List<LinkStreamController> controllerList = [];
      _linkStreamControllers.putIfAbsent(key, () => controllerList);
    }

    return _linkStreamControllers[key];
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    log.warning(
        'Method ${invocation.memberName} not implemented in FakeModuleDriver');
  }
}

class FakeModuleContext implements ModuleContextClient {
  @override
  dynamic noSuchMethod(Invocation invocation) {
    log.warning(
        'Method ${invocation.memberName} not implemented in FakeModuleContext');
  }
}

class FakeModuleControllerClient implements ModuleControllerClient {
  @override
  dynamic noSuchMethod(Invocation invocation) {
    log.warning(
        'Method ${invocation.memberName} not implemented in FakeModuleControllerClient');
  }
}
