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

import 'dart:async';
import 'dart:convert';

import 'package:fidl_fuchsia_mem/fidl.dart' as fuchsia_mem;
import 'package:fidl_fuchsia_modular/fidl.dart';
import 'package:lib.app_driver.dart/module_driver.dart';
import 'package:lib.app.dart/logging.dart';
import 'package:lib.schemas.dart/entity_codec.dart';
import 'package:zircon/zircon.dart';

/// A class which wraps parameters delivered to a module via the
/// [IntentHandler] interface. It provides access to the parameter
/// data in a uniform way, regardless of how the [Intent.parameters]
/// was constructed.
///
/// If a parameter was created with a link, it's possible for the
/// parameter data to change over time. In this case it's better to
/// use [IntentParameters.watchParameterData], which allows modules
/// to observe changes to the parameter. If the module does not care
/// about potential future updates, [IntentParameters.getParameterData]
/// will provide the data directly.
class IntentParameters {
  final Map<String, IntentParameterData> _parameters = {};
  // TODO: Refactor this class to use the new SDK instead of deprecated API
  // ignore: deprecated_member_use_from_same_package
  ModuleDriver _driver;

  /// [moduleDriver] is used to access Entity and Link parameters.
  /// [parameters] are the parmeters from an [Intent].
  IntentParameters({
    // ignore: deprecated_member_use_from_same_package
    ModuleDriver moduleDriver,
    List<IntentParameter> parameters,
  }) {
    _driver = moduleDriver;
    for (var parameter in parameters ?? []) {
      _parameters[parameter.name] = parameter.data;
    }
  }

  /// Returns the data for the parameter with name [parameterName].
  Future<T> getParameterData<T>(
      String parameterName, EntityCodec<T> codec) async {
    IntentParameterData data = _parameters[parameterName];
    if (data == null) {
      throw Exception('Invalid parameter name: $parameterName');
    }

    switch (data.tag) {
      case IntentParameterDataTag.json:
        return _getJsonData(data.json, codec);
      case IntentParameterDataTag.entityReference:
        return _getEntityData(data.entityReference, codec);
      default:
        throw Exception('Unsupported parameter type.');
    }
  }

  T _getJsonData<T>(fuchsia_mem.Buffer json, EntityCodec<T> codec) {
    final vmo = SizedVmo(json.vmo.handle, json.size);
    final data = vmo.read(json.size);
    if (data.status != 0) {
      throw Exception('Failed to read VMO');
    }
    vmo.close();
    return codec.decode(jsonDecode(utf8.decode(data.bytesAsUint8List())));
  }

  Future<T> _getEntityData<T>(
      String entityReference, EntityCodec<T> codec) async {
    final resolver = await _driver.getResolver();
    final entity = await resolver.resolveEntity(entityReference);
    final types = await entity.getTypes();

    if (!types.contains(codec.type)) {
      throw EntityTypeException(codec.type);
    }

    var data = await entity.getData(codec.type);
    return codec.decode(data);
  }

  /// Returns a stream of data. If the parameter is JSON, or an Entity the data
  /// will be added to the stream and the stream will then be closed. If the
  /// parameter is a Link, any observed updates to the Link will also be added
  /// to the stream.
  Stream<T> watchParameterData<T>(String parameterName, EntityCodec<T> codec) {
    IntentParameterData data = _parameters[parameterName];
    if (data == null) {
      throw Exception('Invalid parameter name');
    }

    StreamController<T> controller = new StreamController<T>(
      onListen: () => log.info('watch stream ($parameterName): listening'),
      onPause: () => log.info('watch stream ($parameterName): paused'),
      onResume: () => log.info('watch stream ($parameterName): resuming'),
      onCancel: () => log.info('watch stream ($parameterName): cancelled'),
    );

    switch (data.tag) {
      case IntentParameterDataTag.json:
        controller.add(_getJsonData(data.json, codec));
        controller.close();
        break;
      case IntentParameterDataTag.entityReference:
        _getEntityData(data.entityReference, codec).then((entityData) {
          controller
            ..add(entityData)
            ..close();
        });
        break;
      default:
        throw Exception('Unsupported parameter type: ${data.tag}');
    }
    return controller.stream;
  }
}
