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

// @dart = 2.11

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

import 'dart:convert';

import 'src/binary/sink.dart';
import 'src/binary/source.dart';
import 'info.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.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.writeStringOrNull(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);
    });
  }

  @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);
      }
    });
  }

  _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.writeStringOrNull(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();
    }
    return null;
  }

  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 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,
        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.readStringOrNull();
    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));

        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));

        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.readStringOrNull();
        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;
