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

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

typedef Reader<T> = T Function();
typedef CustomReader<T> = T Function(FileReader reader);
typedef Writer<T> = void Function(T value);
typedef CustomWriter<T> = void Function(FileWriter reader, T value);

const int _typeNullable = 0x01;
const int _typeBool = 0x02;
const int _typeInt = 0x03;
const int _typeString = 0x04;
const int _typeDateTime = 0x05;
const int _typeSet = 0x10;
const int _typeMap = 0x11;
const int _typeCustom = 0xFE;
const int _typeEnd = 0xFF;

class FileReader {
  FileReader(this._buffer) : _endianness = Endian.host;

  final ByteData _buffer;
  final Endian _endianness;
  int _position = 0;

  static Future<FileReader> open(File file) async {
    final Uint8List bytes = await file.readAsBytes();
    return FileReader(bytes.buffer.asByteData(bytes.offsetInBytes, bytes.length));
  }

  void _readType(int expected) {
    final int type = _buffer.getUint8(_position);
    _position += 1;
    if (expected != type) {
      throw FormatException('expected $expected but got $type at byte ${_position - 1}');
    }
  }

  T? readNullOr<T>(Reader<T> reader) {
    _readType(_typeNullable);
    final int result = _buffer.getUint8(_position);
    _position += 1;
    if (result == 0) {
      return null;
    }
    return reader();
  }

  bool readBool() {
    _readType(_typeBool);
    final int result = _buffer.getUint8(_position);
    _position += 1;
    return result != 0x00;
  }

  int readInt() {
    _readType(_typeInt);
    final int result = _buffer.getInt64(_position, _endianness);
    _position += 8;
    return result;
  }

  String readString() {
    _readType(_typeString);
    final int length = readInt();
    final String result = utf8.decode(_buffer.buffer.asUint8List(_buffer.offsetInBytes + _position, length));
    _position += length;
    return result;
  }

  DateTime readDateTime() {
    _readType(_typeDateTime);
    return DateTime.fromMicrosecondsSinceEpoch(readInt(), isUtc: true);
  }

  Reader<Set<T>> readerForSet<T>(Reader<T> reader) {
    return () {
      _readType(_typeSet);
      final int count = readInt();
      final Set<T> result = <T>{};
      for (int index = 0; index < count; index += 1) {
        result.add(reader());
      }
      return result;
    };
  }

  Set<T> readSet<T>(Reader<T> reader) {
    return readerForSet<T>(reader)();
  }

  Reader<Map<K, V>> readerForMap<K, V>(Reader<K> keyReader, Reader<V> valueReader) {
    return () {
      _readType(_typeMap);
      final int count = readInt();
      final Map<K, V> result = <K, V>{};
      for (int index = 0; index < count; index += 1) {
        result[keyReader()] = valueReader();
      }
      return result;
    };
  }

  Map<K, V> readMap<K, V>(Reader<K> keyReader, Reader<V> valueReader) {
    return readerForMap<K, V>(keyReader, valueReader)();
  }

  Reader<T> readerForCustom<T>(CustomReader<T> reader) {
    return () {
      _readType(_typeCustom);
      return reader(this);
    };
  }

  void close() {
    _readType(_typeEnd);
    if (_position != _buffer.lengthInBytes) {
      throw StateError('read failed; position=$_position, expected ${_buffer.lengthInBytes}');
    }
  }
}

class FileWriter {
  FileWriter() : _endianness = Endian.host;

  final BytesBuilder _buffer = BytesBuilder();
  final Endian _endianness;

  void _writeType(int type) {
    _buffer.addByte(type);
  }

  void writeNullOr<T>(T? value, Writer<T> writer) {
    _writeType(_typeNullable);
    if (value == null) {
      _buffer.addByte(0x00);
    } else {
      _buffer.addByte(0xFF);
      writer(value);
    }
  }

  void writeBool(bool value) {
    // ignore: avoid_positional_boolean_parameters
    _writeType(_typeBool);
    _buffer.addByte(value ? 0x01 : 0x00);
  }

  final ByteData _intBuffer = ByteData(8);
  late final Uint8List _intBytes = _intBuffer.buffer.asUint8List();

  void writeInt(int value) {
    _writeType(_typeInt);
    _intBuffer.setInt64(0, value, _endianness);
    _buffer.add(_intBytes);
  }

  void writeString(String value) {
    _writeType(_typeString);
    final List<int> stringBuffer = utf8.encode(value);
    writeInt(stringBuffer.length);
    _buffer.add(stringBuffer);
  }

  void writeDateTime(DateTime value) {
    _writeType(_typeDateTime);
    writeInt(value.microsecondsSinceEpoch);
  }

  Writer<Set<T>> writerForSet<T>(Writer<T> writer) {
    return (Set<T> value) {
      _writeType(_typeSet);
      writeInt(value.length);
      value.forEach(writer);
    };
  }

  void writeSet<T>(Writer<T> writer, Set<T> value) {
    writerForSet<T>(writer)(value);
  }

  Writer<Map<K, V>> writerForMap<K, V>(Writer<K> keyWriter, Writer<V> valueWriter) {
    return (Map<K, V> value) {
      _writeType(_typeMap);
      writeInt(value.length);
      value.forEach((K key, V value) {
        keyWriter(key);
        valueWriter(value);
      });
    };
  }

  void writeMap<K, V>(Writer<K> keyWriter, Writer<V> valueWriter, Map<K, V> value) {
    writerForMap<K, V>(keyWriter, valueWriter)(value);
  }

  Writer<T> writerForCustom<T>(CustomWriter<T> writer) {
    return (T value) {
      _writeType(_typeCustom);
      writer(this, value);
    };
  }

  Future<void> write(File file) async {
    _writeType(_typeEnd);
    final File temp = File('${file.path}.\$\$\$');
    await temp.writeAsBytes(_buffer.takeBytes());
    if (file.existsSync()) {
      await file.delete();
    }
    await temp.rename(file.path);
  }

  ByteData serialize() {
    _writeType(_typeEnd);
    final int length = _buffer.length;
    return _buffer.takeBytes().buffer.asByteData(0, length);
  }
}
