// 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:meta/meta.dart';

/// When an Entity does not support a given type.
class EntityTypeException implements Exception {
  /// The unsuported type.
  final String type;

  /// Create a new [EntityTypeException].
  EntityTypeException(this.type);

  @override
  String toString() =>
      'EntityTypeError: type "$type" is not available for Entity';
}

/// A [Codec] used for handling the the automatic translation of to and from and
/// Entity's source data to the specified Dart type [T].
class EntityCodec<T> extends Codec<T, String> {
  /// The "type" this codec is associated with, similar to mime-type, see
  /// [Entity#GetTypes](https://goo.gl/QJo3tW).
  final String type;

  final _EntityEncoder<T> _encoder;
  final _EntityDecoder<T> _decoder;

  /// Create a new [EntityCodec].
  EntityCodec({
    @required this.type,
    @required _EncodeEntity<T> encode,
    @required _DecodeEntity<T> decode,
  })  : assert(type != null),
        assert(type.isEmpty == false),
        assert(encode != null),
        assert(decode != null),
        _encoder = _EntityEncoder<T>(encode),
        _decoder = _EntityDecoder<T>(decode);

  @override
  _EntityEncoder<T> get encoder => _encoder;

  @override
  _EntityDecoder<T> get decoder => _decoder;
}

typedef _EncodeEntity<T> = String Function(T value);

class _EntityEncoder<T> extends Converter<T, String> {
  final _EncodeEntity<T> encode;

  const _EntityEncoder(this.encode);

  @override
  String convert(T source) {
    return encode(source);
  }
}

typedef _DecodeEntity<T> = T Function(String data);

class _EntityDecoder<T> extends Converter<String, T> {
  final _DecodeEntity<T> decode;

  const _EntityDecoder(this.decode);

  @override
  T convert(String data) => decode(data);

  @override
  Stream<T> bind(Stream<String> source) {
    EntityDecoderSink<T> map(EventSink<T> out) =>
        EntityDecoderSink<T>(out, this);

    return Stream<T>.eventTransformed(source, map);
  }
}

/// Entity data [String]s in, [T] out.
class EntityDecoderSink<T> extends EventSink<String> {
  /// The [EventSink] that values are decoded into. Errors generated by the
  /// decoder are also added to [out].
  final EventSink<T> out;

  /// The decoder to used to convert the source ([Stream<String>]) events.
  final _EntityDecoder<T> decoder;

  /// Create an instance of [EntityDecoderSink], usually via the
  /// [Stream#eventTransformed] constructor.
  EntityDecoderSink(this.out, this.decoder);

  @override
  void add(String data) {
    try {
      T value = decoder.decode(data);
      out.add(value);
    } on Object catch (err, stackTrace) {
      addError(err, stackTrace);
    }
  }

  @override
  void addError(Object e, [StackTrace s]) => out.addError(e, s);

  @override
  void close() => out.close();
}
