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

// This file is hand-formatted.

// This file must not import `dart:ui`, directly or indirectly, as it is
// intended to function even in pure Dart server or CLI environments.
import 'dart:convert';
import 'dart:typed_data';

import 'model.dart';

/// Encode data as a Remote Flutter Widgets binary data blob.
///
/// See also:
///
///  * [decodeDataBlob], which decodes this format.
///  * [encodeLibraryBlob], which uses a superset of this format to encode
///    Remote Flutter Widgets binary library blobs.
Uint8List encodeDataBlob(Object value) {
  final _BlobEncoder encoder = _BlobEncoder();
  encoder.writeSignature(<int>[0xFE, 0x52, 0x57, 0x44]);
  encoder.writeValue(value);
  return encoder.bytes.toBytes();
}

/// Decode a Remote Flutter Widgets binary data blob.
///
/// This data is usually used in conjunction with [DynamicContent].
///
/// This method supports a subset of the format supported by
/// [decodeLibraryBlob]; specifically, it reads a _value_ from that format
/// (rather than a _library_), and disallows values other than maps, lists,
/// ints, doubles, booleans, and strings. See [decodeLibraryBlob] for a
/// description of the format.
///
/// The first four bytes of the file (in hex) are FE 52 57 44.
///
/// See also:
///
///  * [encodeDataBlob], which encodes this format.
///  * [decodeLibraryBlob], which uses a superset of this format to decode
///    Remote Flutter Widgets binary library blobs.
///  * [parseDataFile], which parses the text variant of this format.
Object decodeDataBlob(Uint8List bytes) {
  final _BlobDecoder decoder = _BlobDecoder(bytes.buffer.asByteData(bytes.offsetInBytes, bytes.lengthInBytes));
  decoder.expectSignature(<int>[0xFE, 0x52, 0x57, 0x44]);
  final Object result = decoder.readValue();
  if (!decoder.finished) {
    throw const FormatException('Unexpected trailing bytes after value.');
  }
  return result;
}

/// Encode data as a Remote Flutter Widgets binary library blob.
///
/// See also:
///
///  * [decodeLibraryBlob], which decodes this format.
///  * [encodeDataBlob], which uses a subset of this format to decode
///    Remote Flutter Widgets binary data blobs.
///  * [parseLibraryFile], which parses the text variant of this format.
Uint8List encodeLibraryBlob(RemoteWidgetLibrary value) {
  final _BlobEncoder encoder = _BlobEncoder();
  encoder.writeSignature(<int>[0xFE, 0x52, 0x46, 0x57]);
  encoder.writeLibrary(value);
  return encoder.bytes.toBytes();
}

/// Decode a Remote Flutter Widgets binary library blob.
///
/// Remote widget libraries are usually used in conjunction with a [Runtime].
///
/// ## Format
///
/// This format is a depth-first serialization of the in-memory data structures,
/// using a one-byte tag to identify types when necessary, and using 64 bit
/// integers to encode lengths when necessary.
///
/// The first four bytes of the file (in hex) are FE 52 46 57.
///
/// Primitives in this format are as follows:
///
/// * Integers are encoded as little-endian two's complement 64 bit integers.
///   For example, the number 513 (0x0000000000000201) is encoded as a 0x01
///   byte, a 0x02 byte, and six 0x00 bytes, in that order.
///
/// * Doubles are encoded as little-endian IEEE binary64 numbers.
///
/// * Strings are encoded as an integer length followed by that many UTF-8
///   encoded bytes.
///
///   For example, the string "Hello" would be encoded as:
///
///    05 00 00 00 00 00 00 00 48 65 6C 6C 6F
///
/// * Lists are encoded as an integer length, followed by that many values
///   back to back. When lists are of specific types (e.g. lists of imports),
///   each value in the list is encoded directly (untagged lists); when the list
///   can have multiple types, each value is prefixed by a tag giving the type,
///   followed by the value (tagged lists). For example, a list of integers with
///   the values 1 and 2 in that order would be encoded as:
///
///    02 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00.
///
///   A list of arbitrary values that happens to contain one string "Hello"
///   would be encoded as follows; 0x04 is the tag for "String" (the full list
///   of tags is described below):
///
///    01 00 00 00 00 00 00 00 04 05 00 00 00 00 00 00 00 48 65 6C 6C 6F
///
///   A list of length zero is eight zero bytes with no additional payload.
///
/// * Maps are encoded as an integer length, followed by key/value pairs. For
///   maps where all the keys are strings (e.g. when encoding a [DynamicMap]),
///   the keys are given without tags (an untagged map). For maps where the keys
///   are of arbitrary values, the keys are prefixed by a tag byte (a tagged
///   map; this is only used when encoding [Switch]es). The _values_ are always
///   prefixed by a tag byte (all maps are over values of arbitrary types).
///
///   For example, the map `{ a: 15 }` (when the keys are known to always be
///   strings, so they are untagged) is encoded as follows (0x02 is the tag for
///   integers):
///
///    01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 61 02 0F 00 00 00 00 00 00 00
///
/// Objects are encoded as follows:
///
/// * [RemoteWidgetLibrary] objects are encoded as an untagged list of
///   imports and an untagged list of widget declarations.
///
/// * Imports are encoded as an untagged list of strings, each of which is
///   one of the subparts of the imported library name. For example, `import
///   a.b` is encoded as:
///
///    02 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 61 01 00 00 00 00 00 00 00 62
///
/// * Widget declarations are encoded as a string giving the declaration name,
///   an untagged map for the initial state, and finally the value that
///   represents the root of the widget declaration ([WidgetDeclaration.root],
///   which is always either a [Switch] or a [ConstructorCall]).
///
///   When the widget's initial state is null, it is encoded as an empty map. By
///   extension, this means no distinction is made between a "stateless" remote
///   widget and a "stateful" remote widget whose initial state is empty. (This
///   is reasonable since if the initial state is empty, no state can ever be
///   changed, so the widget is in fact _de facto_ stateless.)
///
/// Values are encoded as a tag byte followed by their data, as follows:
///
/// * Booleans are encoded as just a tag, with the tag being 0x00 for false and
///   0x01 for true.
///
/// * Integers have the tag 0x02, and are encoded as described above (two's
///   complement, little-endian, 64 bit).
///
/// * Doubles have the tag 0x03, and are encoded as described above
///   (little-endian binary64).
///
/// * Strings have the tag 0x04, and are encoded as described above (length
///   followed by UTF-8 bytes).
///
/// * Lists ([DynamicList]) have the tag 0x05, are encoded as described above
///   (length followed by tagged values). (Lists of untagged values are never
///   found in a "value" context.)
///
/// * Maps ([DynamicMap]) have the tag 0x07, are encoded as described above
///   (length followed by pairs of strings and tagged values). (Tagged maps,
///   i.e. those with tagged keys, are never found in a "value" context.)
///
/// * Loops ([Loop]) have the tag 0x08. They are encoded as two tagged values,
///   the [Loop.input] and the [Loop.output].
///
/// * Constructor calls ([ConstructorCall]) have the tag 0x09. They are encoded
///   as a string for the [ConstructorCall.name] followed by an untagged map
///   describing the [ConstructorCall.arguments].
///
/// * Argument, data, and state references ([ArgsReference], [DataReference],
///   and [StateReference] respectively) have tags 0x0A, 0x0B, and 0x0D
///   respectively, and are encoded as tagged lists of strings or integers
///   giving the [Reference.parts] of the reference.
///
/// * Loop references ([LoopReference]) have the tag 0x0C, and are encoded as an
///   integer giving the number of [Loop] objects between the reference and the
///   loop being referenced (this is similar to a De Bruijn index), followed by
///   a tagged list of strings or integers giving the [Reference.parts] of the
///   reference.
///
/// * Switches ([Switch]) have the tag 0x0F. They are encoded as a tagged value
///   describing the control value ([Switch.input]), followed by a tagged map
///   for the various case values ([Switch.outputs]). The default case is
///   represented by a value with tag 0x10 (and no data).
///
///   For example, this switch:
///
///   ```
///   switch (args.a) {
///    0: 'z',
///    1: 'o',
///    default: 'd',
///   }
///   ```
///
///   ...is encoded as follows (including the tag for the switch itself):
///
///    0F 0A 01 00 00 00 00 00  00 00 61 03 00 00 00 00
///    00 00 00 02 00 00 00 00  00 00 00 00 04 01 00 00
///    00 00 00 00 00 7A 02 01  00 00 00 00 00 00 00 04
///    01 00 00 00 00 00 00 00  6F 10 04 01 00 00 00 00
///    00 00 00 64
///
/// * Event handlers have the tag 0x0E, and are encoded as a string
///   ([EventHandler.eventName]) and an untagged map
///   ([EventHandler.eventArguments]).
///
/// * State-setting handlers have the tag 0x11, and are encoded as a tagged list
///   of strings or integers giving the [Reference.parts] of the state reference
///   ([SetStateHandler.stateReference]), followed by the tagged value to which
///   to set that state entry ([SetStateHandler.value]).
///
/// See also:
///
///  * [encodeLibraryBlob], which encodes this format.
///  * [decodeDataBlob], which uses a subset of this format to decode
///    Remote Flutter Widgets binary data blobs.
///  * [parseDataFile], which parses the text variant of this format.
RemoteWidgetLibrary decodeLibraryBlob(Uint8List bytes) {
  final _BlobDecoder decoder = _BlobDecoder(bytes.buffer.asByteData(bytes.offsetInBytes, bytes.lengthInBytes));
  decoder.expectSignature(<int>[0xFE, 0x52, 0x46, 0x57]);
  final RemoteWidgetLibrary result = decoder.readLibrary();
  if (!decoder.finished) {
    throw const FormatException('Unexpected trailing bytes after constructors.');
  }
  return result;
}

// endianess used by this format
const Endian _blobEndian = Endian.little;

// magic signatures
const int _msFalse = 0x00;
const int _msTrue = 0x01;
const int _msInt64 = 0x02;
const int _msBinary64 = 0x03;
const int _msString = 0x04;
const int _msList = 0x05;
const int _msMap = 0x07;
const int _msLoop = 0x08;
const int _msWidget = 0x09;
const int _msArgsReference = 0x0A;
const int _msDataReference = 0x0B;
const int _msLoopReference = 0x0C;
const int _msStateReference = 0x0D;
const int _msEvent = 0x0E;
const int _msSwitch = 0x0F;
const int _msDefault = 0x10;
const int _msSetState = 0x11;

/// API for decoding Remote Flutter Widgets binary blobs.
///
/// Binary data blobs can be decoded by using [readValue].
///
/// Binary library blobs can be decoded by using [readLibrary].
///
/// In either case, if [finished] returns false after parsing the root token,
/// then there is unexpected further data in the file.
class _BlobDecoder {
  _BlobDecoder(this.bytes);

  final ByteData bytes;

  int _cursor = 0;

  bool get finished => _cursor >= bytes.lengthInBytes;

  void _advance(String context, int length) {
    if (_cursor + length > bytes.lengthInBytes) {
      throw FormatException('Could not read $context at offset $_cursor: unexpected end of file.');
    }
    _cursor += length;
  }

  int _readByte() {
    final int byteOffset = _cursor;
    _advance('byte', 1);
    return bytes.getUint8(byteOffset);
  }

  int _readInt64() {
    final int byteOffset = _cursor;
    _advance('int64', 8);
    return bytes.getInt64(byteOffset, _blobEndian);
  }

  double _readDouble() {
    final int byteOffset = _cursor;
    _advance('double', 8);
    return bytes.getFloat64(byteOffset, _blobEndian);
  }

  String _readString() {
    final int length = _readInt64();
    final int byteOffset = _cursor;
    _advance('string', length);
    return utf8.decode(bytes.buffer.asUint8List(bytes.offsetInBytes + byteOffset, length));
  }

  List<Object> _readPartList() {
    return List<Object>.generate(_readInt64(), (int index) {
      final int type = _readByte();
      switch (type) {
        case _msString:
          return _readString();
        case _msInt64:
          return _readInt64();
        default:
          throw FormatException('Invalid reference type 0x${type.toRadixString(16).toUpperCase().padLeft(2, "0")} while decoding blob.');
      }
    });
  }

  Map<String, Object?>? _readMap(Object Function() readNode, { bool nullIfEmpty = false }) {
    final int count = _readInt64();
    if (count == 0 && nullIfEmpty) {
      return null;
    }
    return DynamicMap.fromEntries(
      Iterable<MapEntry<String, Object>>.generate(
        count,
        (int index) => MapEntry<String, Object>(
          _readString(),
          readNode(),
        ),
      ),
    );
  }

  Object? _readSwitchKey() {
    final int type = _readByte();
    if (type == _msDefault) {
      return null;
    }
    return _parseArgument(type);
  }

  Switch _readSwitch() {
    final Object value = _readArgument();
    final int count = _readInt64();
    final Map<Object?, Object> cases = Map<Object?, Object>.fromEntries(
      Iterable<MapEntry<Object?, Object>>.generate(
        count,
        (int index) => MapEntry<Object?, Object>(
          _readSwitchKey(),
          _readArgument(),
        ),
      ),
    );
    return Switch(value, cases);
  }

  Object _parseValue(int type, Object Function() readNode) {
    switch (type) {
      case _msFalse:
        return false;
      case _msTrue:
        return true;
      case _msInt64:
        return _readInt64();
      case _msBinary64:
        return _readDouble();
      case _msString:
        return _readString();
      case _msList:
        return DynamicList.generate(_readInt64(), (int index) => readNode());
      case _msMap:
        return _readMap(readNode)!;
      default: throw FormatException('Unrecognized data type 0x${type.toRadixString(16).toUpperCase().padLeft(2, "0")} while decoding blob.');
    }
  }

  Object readValue() {
    final int type = _readByte();
    return _parseValue(type, readValue);
  }

  Object _parseArgument(int type) {
    switch (type) {
      case _msLoop:
        return Loop(_readArgument(), _readArgument());
      case _msWidget:
        return _readWidget();
      case _msArgsReference:
        return ArgsReference(_readPartList());
      case _msDataReference:
        return DataReference(_readPartList());
      case _msLoopReference:
        return LoopReference(_readInt64(), _readPartList());
      case _msStateReference:
        return StateReference(_readPartList());
      case _msEvent:
        return EventHandler(_readString(), _readMap(_readArgument)!);
      case _msSwitch:
        return _readSwitch();
      case _msSetState:
        return SetStateHandler(StateReference(_readPartList()), _readArgument());
      default:
        return _parseValue(type, _readArgument);
    }
  }

  Object _readArgument() {
    final int type = _readByte();
    return _parseArgument(type);
  }

  ConstructorCall _readWidget() {
    final String name = _readString();
    return ConstructorCall(name, _readMap(_readArgument)!);
  }

  WidgetDeclaration _readDeclaration() {
    final String name = _readString();
    final DynamicMap? initialState = _readMap(readValue, nullIfEmpty: true);
    final int type = _readByte();
    final BlobNode root;
    switch (type) {
      case _msSwitch:
        root = _readSwitch();
        break;
      case _msWidget:
        root = _readWidget();
        break;
      default:
        throw FormatException('Unrecognized data type 0x${type.toRadixString(16).toUpperCase().padLeft(2, "0")} while decoding widget declaration root.');
    }
    return WidgetDeclaration(name, initialState, root);
  }

  List<WidgetDeclaration> _readDeclarationList() {
    return List<WidgetDeclaration>.generate(_readInt64(), (int index) => _readDeclaration());
  }

  Import _readImport() {
    return Import(LibraryName(List<String>.generate(_readInt64(), (int index) => _readString())));
  }

  List<Import> _readImportList() {
    return List<Import>.generate(_readInt64(), (int index) => _readImport());
  }

  RemoteWidgetLibrary readLibrary() {
    return RemoteWidgetLibrary(_readImportList(), _readDeclarationList());
  }

  void expectSignature(List<int> signature) {
    assert(signature.length == 4);
    final List<int> bytes = <int>[];
    bool match = true;
    for (final int byte in signature) {
      final int read = _readByte();
      bytes.add(read);
      if (read != byte) {
        match = false;
      }
    }
    if (!match) {
      throw FormatException(
        'File signature mismatch. '
        'Expected ${signature.map<String>((int byte) => byte.toRadixString(16).toUpperCase().padLeft(2, "0")).join(" ")} '
        'but found ${bytes.map<String>((int byte) => byte.toRadixString(16).toUpperCase().padLeft(2, "0")).join(" ")}.'
      );
    }
  }
}

/// API for encoding Remote Flutter Widgets binary blobs.
///
/// Binary data blobs can be serialized using [writeValue].
///
/// Binary library blobs can be serialized using [writeLibrary].
///
/// The output is in [bytes], and can be cleared manually to reuse the [_BlobEncoder].
class _BlobEncoder {
  _BlobEncoder();

  static final Uint8List _scratchOut = Uint8List(8);
  static final ByteData _scratchIn = _scratchOut.buffer.asByteData(_scratchOut.offsetInBytes, _scratchOut.lengthInBytes);

  final BytesBuilder bytes = BytesBuilder(); // copying builder -- we repeatedly add _scratchOut after changing it

  void _writeInt64(int value) {
    _scratchIn.setInt64(0, value, _blobEndian);
    bytes.add(_scratchOut);
  }

  void _writeString(String value) {
    final Uint8List buffer = utf8.encode(value) as Uint8List;
    _writeInt64(buffer.length);
    bytes.add(buffer);
  }

  void _writeMap(DynamicMap value, void Function(Object? value) recurse) {
    _writeInt64(value.length);
    value.forEach((String key, Object? value) {
      _writeString(key);
      recurse(value);
    });
  }

  void _writePart(Object? value) {
    if (value is int) {
      bytes.addByte(_msInt64);
      _writeInt64(value);
    } else if (value is String) {
      bytes.addByte(_msString);
      _writeString(value);
    } else {
      throw StateError('Unexpected type ${value.runtimeType} while encoding blob.');
    }
  }

  void _writeValue(Object? value, void Function(Object? value) recurse) {
    if (value == false) {
      bytes.addByte(_msFalse);
    } else if (value == true) {
      bytes.addByte(_msTrue);
    } else if (value is double) {
      bytes.addByte(_msBinary64);
      _scratchIn.setFloat64(0, value, _blobEndian);
      bytes.add(_scratchOut);
    } else if (value is DynamicList) {
      bytes.addByte(_msList);
      _writeInt64(value.length);
      value.forEach(recurse);
    } else if (value is DynamicMap) {
      bytes.addByte(_msMap);
      _writeMap(value, recurse);
    } else {
      _writePart(value);
    }
  }

  void writeValue(Object? value) {
    _writeValue(value, writeValue);
  }

  void _writeArgument(Object? value) {
    if (value is Loop) {
      bytes.addByte(_msLoop);
      _writeArgument(value.input);
      _writeArgument(value.output);
    } else if (value is ConstructorCall) {
      bytes.addByte(_msWidget);
      _writeString(value.name);
      _writeMap(value.arguments, _writeArgument);
    } else if (value is ArgsReference) {
      bytes.addByte(_msArgsReference);
      _writeInt64(value.parts.length);
      value.parts.forEach(_writePart);
    } else if (value is DataReference) {
      bytes.addByte(_msDataReference);
      _writeInt64(value.parts.length);
      value.parts.forEach(_writePart);
    } else if (value is LoopReference) {
      bytes.addByte(_msLoopReference);
      _writeInt64(value.loop);
      _writeInt64(value.parts.length);
      value.parts.forEach(_writePart);
    } else if (value is StateReference) {
      bytes.addByte(_msStateReference);
      _writeInt64(value.parts.length);
      value.parts.forEach(_writePart);
    } else if (value is EventHandler) {
      bytes.addByte(_msEvent);
      _writeString(value.eventName);
      _writeMap(value.eventArguments, _writeArgument);
    } else if (value is Switch) {
      bytes.addByte(_msSwitch);
      _writeArgument(value.input);
      _writeInt64(value.outputs.length);
      value.outputs.forEach((Object? key, Object value) {
        if (key == null) {
          bytes.addByte(_msDefault);
        } else {
          _writeArgument(key);
        }
        _writeArgument(value);
      });
    } else if (value is SetStateHandler) {
      bytes.addByte(_msSetState);
      final StateReference reference = value.stateReference as StateReference;
      _writeInt64(reference.parts.length);
      reference.parts.forEach(_writePart);
      _writeArgument(value.value);
    } else {
      assert(value is! BlobNode);
      _writeValue(value, _writeArgument);
    }
  }

  void _writeDeclarationList(List<WidgetDeclaration> value) {
    _writeInt64(value.length);
    for (final WidgetDeclaration declaration in value) {
      _writeString(declaration.name);
      if (declaration.initialState != null) {
        _writeMap(declaration.initialState!, _writeArgument);
      } else {
        _writeInt64(0);
      }
      _writeArgument(declaration.root);
    }
  }

  void _writeImportList(List<Import> value) {
    _writeInt64(value.length);
    for (final Import import in value) {
      _writeInt64(import.name.parts.length);
      import.name.parts.forEach(_writeString);
    }
  }

  void writeLibrary(RemoteWidgetLibrary library) {
    _writeImportList(library.imports);
    _writeDeclarationList(library.widgets);
  }

  void writeSignature(List<int> signature) {
    assert(signature.length == 4);
    bytes.add(signature);
  }
}
