// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Info serialization to a binary form.
///
/// Unlike the JSON codec, this serialization is designed to be streamed.

import 'dart:convert';

import 'info.dart';
import 'src/binary/sink.dart';
import 'src/binary/source.dart';

void encode(AllInfo info, Sink<List<int>> sink) {
  BinaryPrinter(BinarySink(sink)).visitAll(info);
}

AllInfo decode(List<int> data) {
  return BinaryReader(BinarySource(data)).readAll();
}

class BinaryPrinter implements InfoVisitor<void> {
  final BinarySink sink;

  BinaryPrinter(this.sink);

  void writeDate(DateTime date) {
    sink.writeString(date.toIso8601String());
  }

  void writeDuration(Duration duration) {
    sink.writeInt(duration.inMicroseconds);
  }

  void writeInfoWithKind(Info info) {
    sink.writeEnum(info.kind);
    info.accept(this);
  }

  @override
  void visitAll(AllInfo info) {
    sink.writeInt(info.version);
    sink.writeInt(info.minorVersion);
    sink.writeList(info.libraries, visitLibrary);
    // TODO(sigmund): synthesize the following lists instead of serializing the
    // values again.
    sink.writeList(info.classes, visitClass);
    sink.writeList(info.classTypes, visitClassType);
    sink.writeList(info.functions, visitFunction);
    sink.writeList(info.typedefs, visitTypedef);
    sink.writeList(info.fields, visitField);
    sink.writeList(info.constants, visitConstant);
    sink.writeList(info.closures, visitClosure);

    void writeDependencies(CodeInfo info) {
      sink.writeList(info.uses, _writeDependencyInfo);
    }

    info.fields.forEach(writeDependencies);
    info.functions.forEach(writeDependencies);

    sink.writeInt(info.dependencies.length);
    info.dependencies.forEach((Info key, List<Info> values) {
      writeInfoWithKind(key);
      sink.writeList(values, writeInfoWithKind);
    });
    sink.writeList(info.outputUnits, visitOutput);
    sink.writeString(jsonEncode(info.deferredFiles));
    visitProgram(info.program!);
    sink.close();
  }

  @override
  void visitProgram(ProgramInfo info) {
    visitFunction(info.entrypoint);
    sink.writeInt(info.size);
    sink.writeString(info.ramUsage);
    sink.writeStringOrNull(info.dart2jsVersion);
    writeDate(info.compilationMoment);
    writeDuration(info.compilationDuration);
    // Note: we don't record the 'toJsonDuration' field. Consider deleting it?
    writeDuration(info.dumpInfoDuration);
    sink.writeBool(info.noSuchMethodEnabled);
    sink.writeBool(info.isRuntimeTypeUsed);
    sink.writeBool(info.isIsolateInUse);
    sink.writeBool(info.isFunctionApplyUsed);
    sink.writeBool(info.isMirrorsUsed);
    sink.writeBool(info.minified);
  }

  void _visitBasicInfo(BasicInfo info) {
    sink.writeString(info.name);
    sink.writeInt(info.size);
    sink.writeStringOrNull(info.coverageId);
    _writeOutputOrNull(info.outputUnit);
    // Note: parent-pointers are not serialized, they get deduced during deserialization.
  }

  @override
  void visitLibrary(LibraryInfo library) {
    sink.writeCached(library, (LibraryInfo info) {
      sink.writeUri(info.uri);
      _visitBasicInfo(info);
      sink.writeList(info.topLevelFunctions, visitFunction);
      sink.writeList(info.topLevelVariables, visitField);
      sink.writeList(info.classes, visitClass);
      sink.writeList(info.classTypes, visitClassType);
      sink.writeList(info.typedefs, visitTypedef);
    });
  }

  @override
  void visitClass(ClassInfo cls) {
    sink.writeCached(cls, (ClassInfo info) {
      _visitBasicInfo(info);
      sink.writeBool(info.isAbstract);
      sink.writeList(info.fields, visitField);
      sink.writeList(info.functions, visitFunction);
      sink.writeList(info.supers, visitClass);
    });
  }

  @override
  void visitClassType(ClassTypeInfo cls) {
    sink.writeCached(cls, (ClassTypeInfo info) {
      _visitBasicInfo(info);
    });
  }

  @override
  void visitField(FieldInfo field) {
    sink.writeCached(field, (FieldInfo info) {
      _visitBasicInfo(info);
      sink.writeList(info.closures, visitClosure);
      sink.writeString(info.inferredType);
      sink.writeList(info.code, _visitCodeSpan);
      sink.writeString(info.type);
      sink.writeBool(info.isConst);
      if (info.isConst) {
        _writeConstantOrNull(info.initializer);
      }
    });
  }

  void _visitCodeSpan(CodeSpan code) {
    sink.writeIntOrNull(code.start);
    sink.writeIntOrNull(code.end);
    sink.writeStringOrNull(code.text);
  }

  void _writeConstantOrNull(ConstantInfo? info) {
    sink.writeBool(info != null);
    if (info != null) {
      visitConstant(info);
    }
  }

  @override
  void visitConstant(ConstantInfo constant) {
    sink.writeCached(constant, (ConstantInfo info) {
      _visitBasicInfo(info);
      sink.writeList(info.code, _visitCodeSpan);
    });
  }

  void _visitFunctionModifiers(FunctionModifiers mods) {
    int value = 0;
    if (mods.isStatic) value |= _staticMask;
    if (mods.isConst) value |= _constMask;
    if (mods.isFactory) value |= _factoryMask;
    if (mods.isExternal) value |= _externalMask;
    sink.writeInt(value);
  }

  void _visitParameterInfo(ParameterInfo info) {
    sink.writeString(info.name);
    sink.writeString(info.type);
    sink.writeString(info.declaredType);
  }

  @override
  void visitFunction(FunctionInfo function) {
    sink.writeCached(function, (FunctionInfo info) {
      _visitBasicInfo(info);
      sink.writeInt(info.functionKind);
      sink.writeList(info.closures, visitClosure);
      _visitFunctionModifiers(info.modifiers);
      sink.writeString(info.returnType);
      sink.writeString(info.inferredReturnType);
      sink.writeList(info.parameters, _visitParameterInfo);
      sink.writeString(info.sideEffects);
      sink.writeIntOrNull(info.inlinedCount);
      sink.writeList(info.code, _visitCodeSpan);
      sink.writeString(info.type);
    });
  }

  void _writeDependencyInfo(DependencyInfo info) {
    writeInfoWithKind(info.target);
    sink.writeStringOrNull(info.mask);
  }

  @override
  void visitClosure(ClosureInfo closure) {
    sink.writeCached(closure, (ClosureInfo info) {
      _visitBasicInfo(info);
      visitFunction(info.function);
    });
  }

  @override
  void visitTypedef(TypedefInfo typedef) {
    sink.writeCached(typedef, (TypedefInfo info) {
      _visitBasicInfo(info);
      sink.writeString(info.type);
    });
  }

  void _writeOutputOrNull(OutputUnitInfo? info) {
    sink.writeBool(info != null);
    if (info != null) {
      visitOutput(info);
    }
  }

  @override
  void visitOutput(OutputUnitInfo output) {
    sink.writeCached(output, (OutputUnitInfo info) {
      _visitBasicInfo(info);
      sink.writeString(info.filename);
      sink.writeList(info.imports, sink.writeString);
    });
  }
}

class BinaryReader {
  final BinarySource source;
  BinaryReader(this.source);

  DateTime readDate() {
    return DateTime.parse(source.readString());
  }

  Duration readDuration() {
    return Duration(microseconds: source.readInt());
  }

  Info readInfoWithKind() {
    InfoKind kind = source.readEnum(InfoKind.values);
    switch (kind) {
      case InfoKind.library:
        return readLibrary();
      case InfoKind.clazz:
        return readClass();
      case InfoKind.classType:
        return readClassType();
      case InfoKind.function:
        return readFunction();
      case InfoKind.field:
        return readField();
      case InfoKind.constant:
        return readConstant();
      case InfoKind.outputUnit:
        return readOutput();
      case InfoKind.typedef:
        return readTypedef();
      case InfoKind.closure:
        return readClosure();
      case InfoKind.package:
        throw StateError('Binary serialization is not supported for '
            'PackageInfo');
    }
  }

  AllInfo readAll() {
    var info = AllInfo();
    int version = source.readInt();
    int minorVersion = source.readInt();
    if (info.version != version || info.minorVersion != minorVersion) {
      print("warning: data was encoded with format version "
          "$version.$minorVersion, but decoded with "
          "${info.version}.${info.minorVersion}");
    }
    info.libraries.addAll(source.readList(readLibrary));
    info.classes.addAll(source.readList(readClass));
    info.classTypes.addAll(source.readList(readClassType));
    info.functions.addAll(source.readList(readFunction));
    info.typedefs.addAll(source.readList(readTypedef));
    info.fields.addAll(source.readList(readField));
    info.constants.addAll(source.readList(readConstant));
    info.closures.addAll(source.readList(readClosure));

    void readDependencies(CodeInfo info) {
      info.uses = source.readList(_readDependencyInfo);
    }

    info.fields.forEach(readDependencies);
    info.functions.forEach(readDependencies);

    int dependenciesTotal = source.readInt();
    while (dependenciesTotal > 0) {
      Info key = readInfoWithKind();
      List<Info> values = source.readList(readInfoWithKind);
      info.dependencies[key] = values;
      dependenciesTotal--;
    }

    info.outputUnits.addAll(source.readList(readOutput));

    Map<String, Map<String, dynamic>> map =
        jsonDecode(source.readString()).cast<String, Map<String, dynamic>>();
    for (final library in map.values) {
      if (library['imports'] != null) {
        // The importMap needs to be typed as <String, List<String>>, but the
        // json parser produces <String, dynamic>.
        final importMap = library['imports'] as Map<String, dynamic>;
        importMap.forEach((prefix, files) {
          importMap[prefix] = (files as List<dynamic>).cast<String>();
        });
        library['imports'] = importMap.cast<String, List<String>>();
      }
    }
    info.deferredFiles = map;
    info.program = readProgram();
    return info;
  }

  ProgramInfo readProgram() {
    final entrypoint = readFunction();
    final size = source.readInt();
    final ramUsage = source.readString();
    final dart2jsVersion = source.readStringOrNull();
    final compilationMoment = readDate();
    final compilationDuration = readDuration();
    final toJsonDuration = Duration(microseconds: 0);
    final dumpInfoDuration = readDuration();
    final noSuchMethodEnabled = source.readBool();
    final isRuntimeTypeUsed = source.readBool();
    final isIsolateInUse = source.readBool();
    final isFunctionApplyUsed = source.readBool();
    final isMirrorsUsed = source.readBool();
    final minified = source.readBool();
    return ProgramInfo(
        entrypoint: entrypoint,
        size: size,
        ramUsage: ramUsage,
        dart2jsVersion: dart2jsVersion,
        compilationMoment: compilationMoment,
        compilationDuration: compilationDuration,
        toJsonDuration: toJsonDuration,
        dumpInfoDuration: dumpInfoDuration,
        noSuchMethodEnabled: noSuchMethodEnabled,
        isRuntimeTypeUsed: isRuntimeTypeUsed,
        isIsolateInUse: isIsolateInUse,
        isFunctionApplyUsed: isFunctionApplyUsed,
        isMirrorsUsed: isMirrorsUsed,
        minified: minified);
  }

  void _readBasicInfo(BasicInfo info) {
    info.name = source.readString();
    info.size = source.readInt();
    info.coverageId = source.readStringOrNull();
    info.outputUnit = _readOutputOrNull();
    // Note: parent pointers are added when deserializing parent nodes.
  }

  LibraryInfo readLibrary() => source.readCached<LibraryInfo>(() {
        LibraryInfo info = LibraryInfo.internal();
        info.uri = source.readUri();
        _readBasicInfo(info);
        info.topLevelFunctions.addAll(source.readList(readFunction));
        info.topLevelVariables.addAll(source.readList(readField));
        info.classes.addAll(source.readList(readClass));
        info.classTypes.addAll(source.readList(readClassType));
        info.typedefs.addAll(source.readList(readTypedef));

        LibraryInfo setParent(BasicInfo child) => child.parent = info;
        info.topLevelFunctions.forEach(setParent);
        info.topLevelVariables.forEach(setParent);
        info.classes.forEach(setParent);
        info.classTypes.forEach(setParent);
        info.typedefs.forEach(setParent);
        return info;
      });

  ClassInfo readClass() => source.readCached<ClassInfo>(() {
        ClassInfo info = ClassInfo.internal();
        _readBasicInfo(info);
        info.isAbstract = source.readBool();
        info.fields.addAll(source.readList(readField));
        info.functions.addAll(source.readList(readFunction));
        info.supers.addAll(source.readList(readClass));

        ClassInfo setParent(BasicInfo child) => child.parent = info;
        info.fields.forEach(setParent);
        info.functions.forEach(setParent);
        return info;
      });

  ClassTypeInfo readClassType() => source.readCached<ClassTypeInfo>(() {
        var info = ClassTypeInfo.internal();
        _readBasicInfo(info);
        return info;
      });

  FieldInfo readField() => source.readCached<FieldInfo>(() {
        FieldInfo info = FieldInfo.internal();
        _readBasicInfo(info);
        info.closures = source.readList(readClosure);
        info.inferredType = source.readString();
        info.code = source.readList(_readCodeSpan);
        info.type = source.readString();
        info.isConst = source.readBool();
        if (info.isConst) {
          info.initializer = _readConstantOrNull();
        }
        for (var c in info.closures) {
          c.parent = info;
        }
        return info;
      });

  CodeSpan _readCodeSpan() {
    final start = source.readIntOrNull();
    final end = source.readIntOrNull();
    final text = source.readStringOrNull();
    return CodeSpan(start: start, end: end, text: text);
  }

  ConstantInfo? _readConstantOrNull() {
    bool hasOutput = source.readBool();
    if (hasOutput) return readConstant();
    return null;
  }

  ConstantInfo readConstant() => source.readCached<ConstantInfo>(() {
        ConstantInfo info = ConstantInfo.internal();
        _readBasicInfo(info);
        info.code = source.readList(_readCodeSpan);
        return info;
      });

  FunctionModifiers _readFunctionModifiers() {
    int value = source.readInt();
    return FunctionModifiers(
        isStatic: value & _staticMask != 0,
        isConst: value & _constMask != 0,
        isFactory: value & _factoryMask != 0,
        isExternal: value & _externalMask != 0);
  }

  ParameterInfo _readParameterInfo() {
    return ParameterInfo(
        source.readString(), source.readString(), source.readString());
  }

  FunctionInfo readFunction() => source.readCached<FunctionInfo>(() {
        FunctionInfo info = FunctionInfo.internal();
        _readBasicInfo(info);
        info.functionKind = source.readInt();
        info.closures = source.readList(readClosure);
        info.modifiers = _readFunctionModifiers();
        info.returnType = source.readString();
        info.inferredReturnType = source.readString();
        info.parameters = source.readList(_readParameterInfo);
        info.sideEffects = source.readString();
        info.inlinedCount = source.readIntOrNull();
        info.code = source.readList(_readCodeSpan);
        info.type = source.readString();
        for (var c in info.closures) {
          c.parent = info;
        }
        return info;
      });

  DependencyInfo _readDependencyInfo() =>
      DependencyInfo(readInfoWithKind(), source.readStringOrNull());

  ClosureInfo readClosure() => source.readCached<ClosureInfo>(() {
        ClosureInfo info = ClosureInfo.internal();
        _readBasicInfo(info);
        info.function = readFunction();
        info.function.parent = info;
        return info;
      });

  TypedefInfo readTypedef() => source.readCached<TypedefInfo>(() {
        TypedefInfo info = TypedefInfo.internal();
        _readBasicInfo(info);
        info.type = source.readString();
        return info;
      });

  OutputUnitInfo? _readOutputOrNull() {
    bool hasOutput = source.readBool();
    if (hasOutput) return readOutput();
    return null;
  }

  OutputUnitInfo readOutput() => source.readCached<OutputUnitInfo>(() {
        OutputUnitInfo info = OutputUnitInfo.internal();
        _readBasicInfo(info);
        info.filename = source.readString();
        info.imports.addAll(source.readList(source.readString));
        return info;
      });
}

const int _staticMask = 1 << 3;
const int _constMask = 1 << 2;
const int _factoryMask = 1 << 1;
const int _externalMask = 1 << 0;
