// Copyright (c) 2023, 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.

import '../ir/ir.dart' as ir;
import 'serializer.dart';

abstract class Section implements Serializable {
  final List<int> watchPoints;

  Section(this.watchPoints);

  @override
  void serialize(Serializer s) {
    final contents = Serializer();
    serializeContents(contents);
    final data = contents.data;
    if (data.isNotEmpty) {
      s.writeByte(id);
      s.writeUnsigned(data.length);
      s.sourceMapSerializer
          .copyMappings(contents.sourceMapSerializer, s.offset);
      s.writeData(contents, watchPoints);
    }
  }

  int get id;

  void serializeContents(Serializer s);
}

class TypeSection extends Section {
  final ir.Types types;

  TypeSection(this.types, super.watchPoints);

  List<List<ir.DefType>> get recursionGroups => types.recursionGroups;

  @override
  int get id => 1;

  @override
  void serializeContents(Serializer s) {
    if (types.recursionGroups.isNotEmpty) {
      s.writeUnsigned(types.recursionGroups.length);
      int typeIndex = 0;

      // Set all the indices first since types can be referenced before they are
      // serialized.
      for (final group in recursionGroups) {
        assert(group.isNotEmpty, 'Empty groups are not allowed.');

        for (final type in group) {
          type.index = typeIndex++;
        }
      }
      for (final group in recursionGroups) {
        s.writeByte(0x4E); // -0x32
        s.writeUnsigned(group.length);
        for (final type in group) {
          assert(
              type.superType == null ||
                  type.superType!.index <= group.last.index,
              "Type '$type' has a supertype in a later recursion group");
          assert(
              type.constituentTypes
                  .whereType<ir.RefType>()
                  .map((t) => t.heapType)
                  .whereType<ir.DefType>()
                  .every((d) => d.index <= group.last.index),
              "Type '$type' depends on a type in a later recursion group");
          type.serializeDefinition(s);
        }
      }
    }
  }
}

class ImportSection extends Section {
  final List<ir.Import> imports;

  ImportSection(this.imports, super.watchPoints);

  @override
  int get id => 2;

  @override
  void serializeContents(Serializer s) {
    if (imports.isNotEmpty) {
      s.writeList(imports);
    }
  }
}

class FunctionSection extends Section {
  final List<ir.DefinedFunction> functions;

  FunctionSection(this.functions, super.watchPoints);

  @override
  int get id => 3;

  @override
  void serializeContents(Serializer s) {
    if (functions.isNotEmpty) {
      s.writeUnsigned(functions.length);
      for (final function in functions) {
        s.writeUnsigned(function.type.index);
      }
    }
  }
}

class TableSection extends Section {
  final List<ir.DefinedTable> tables;

  TableSection(this.tables, super.watchPOints);

  @override
  int get id => 4;

  @override
  void serializeContents(Serializer s) {
    if (tables.isNotEmpty) {
      s.writeList(tables);
    }
  }
}

class MemorySection extends Section {
  final List<ir.DefinedMemory> memories;

  MemorySection(this.memories, super.watchPoints);

  @override
  int get id => 5;

  @override
  void serializeContents(Serializer s) {
    if (memories.isNotEmpty) {
      s.writeList(memories);
    }
  }
}

class TagSection extends Section {
  final List<ir.DefinedTag> tags;

  TagSection(this.tags, super.watchPoints);

  @override
  int get id => 13;

  @override
  void serializeContents(Serializer s) {
    if (tags.isNotEmpty) {
      s.writeList(tags);
    }
  }
}

class GlobalSection extends Section {
  final List<ir.DefinedGlobal> globals;

  GlobalSection(this.globals, super.watchPoints);

  @override
  int get id => 6;

  @override
  void serializeContents(Serializer s) {
    if (globals.isNotEmpty) {
      s.writeList(globals);
    }
  }
}

class ExportSection extends Section {
  final List<ir.Export> exports;

  ExportSection(this.exports, super.watchPoints);

  @override
  int get id => 7;

  @override
  void serializeContents(Serializer s) {
    if (exports.isNotEmpty) {
      s.writeList(exports);
    }
  }
}

class StartSection extends Section {
  final ir.BaseFunction? startFunction;

  StartSection(this.startFunction, super.watchPoints);

  @override
  int get id => 8;

  @override
  void serializeContents(Serializer s) {
    if (startFunction != null) {
      s.writeUnsigned(startFunction!.index);
    }
  }
}

sealed class _Element implements Serializable {}

class _TableElement implements _Element {
  final ir.Table table;
  final int startIndex;
  final List<ir.BaseFunction> entries = [];

  _TableElement(this.table, this.startIndex);

  @override
  void serialize(Serializer s) {
    if (table.index != 0) {
      s.writeByte(0x06);
      s.writeUnsigned(table.index);
    } else {
      s.writeByte(0x00);
    }
    s.writeByte(0x41); // i32.const
    s.writeSigned(startIndex);
    s.writeByte(0x0B); // end
    if (table.index != 0) {
      s.write(table.type);
    }
    s.writeUnsigned(entries.length);
    for (var entry in entries) {
      if (table.index == 0) {
        s.writeUnsigned(entry.index);
      } else {
        s.writeByte(0xD2); // ref.func
        s.writeSigned(entry.index);
        s.writeByte(0x0B); // end
      }
    }
  }
}

class _DeclaredElement implements _Element {
  final List<ir.BaseFunction> entries;

  _DeclaredElement(this.entries);

  @override
  void serialize(Serializer s) {
    if (entries.isEmpty) return;
    s.writeByte(0x03);
    s.writeByte(0x00);

    s.writeUnsigned(entries.length);
    for (final entry in entries) {
      s.writeUnsigned(entry.index);
    }
  }
}

class ElementSection extends Section {
  final List<ir.DefinedTable> definedTables;
  final List<ir.ImportedTable> importedTables;
  final List<ir.BaseFunction> declaredFunctions;

  ElementSection(this.definedTables, this.importedTables,
      this.declaredFunctions, super.watchPoints);

  @override
  int get id => 9;

  @override
  void serializeContents(Serializer s) {
    // Group nonempty element entries into contiguous stretches and serialize
    // each stretch as an element.
    List<_Element> elements = [];
    for (final table in definedTables) {
      _TableElement? current;
      for (int i = 0; i < table.elements.length; i++) {
        ir.BaseFunction? function = table.elements[i];
        if (function != null) {
          if (current == null) {
            current = _TableElement(table, i);
            elements.add(current);
          }
          current.entries.add(function);
        } else {
          current = null;
        }
      }
    }
    for (final table in importedTables) {
      final entries = [...table.setElements.entries]
        ..sort((a, b) => a.key.compareTo(b.key));

      _TableElement? current;
      int lastIndex = -2;
      for (final entry in entries) {
        final index = entry.key;
        final function = entry.value;
        if (index != lastIndex + 1) {
          current = _TableElement(table, index);
          elements.add(current);
        }
        current!.entries.add(function);
        lastIndex = index;
      }
    }
    for (final func in declaredFunctions) {
      elements.add(_DeclaredElement([func]));
    }
    if (elements.isNotEmpty) {
      s.writeList(elements);
    }
  }
}

class DataCountSection extends Section {
  final List<ir.DataSegment> dataSegments;

  DataCountSection(this.dataSegments, super.watchPoints);

  @override
  int get id => 12;

  @override
  void serializeContents(Serializer s) {
    if (dataSegments.isNotEmpty) {
      s.writeUnsigned(dataSegments.length);
    }
  }
}

class CodeSection extends Section {
  final List<ir.DefinedFunction> functions;

  CodeSection(this.functions, super.watchPoints);

  @override
  int get id => 10;

  @override
  void serializeContents(Serializer s) {
    if (functions.isNotEmpty) {
      s.writeList(functions);
    }
  }
}

class DataSection extends Section {
  final List<ir.DataSegment> dataSegments;

  DataSection(this.dataSegments, super.watchPoints);

  @override
  int get id => 11;

  @override
  void serializeContents(Serializer s) {
    if (dataSegments.isNotEmpty) {
      s.writeList(dataSegments);
    }
  }
}

abstract class CustomSection extends Section {
  CustomSection(super.watchPoints);

  @override
  int get id => 0;
}

class NameSection extends CustomSection {
  final String moduleName;
  final List<ir.BaseFunction> functions;
  final List<List<ir.DefType>> types;
  final List<ir.Global> globals;

  NameSection(
    this.moduleName,
    this.functions,
    this.types,
    this.globals,
    super.watchPoints,
  );

  @override
  void serializeContents(Serializer s) {
    final moduleNameSubsection = Serializer();
    moduleNameSubsection.writeName(moduleName);

    int functionNameCount = 0;
    final functionNames = Serializer();
    for (int i = 0; i < functions.length; i++) {
      final String? functionName = functions[i].functionName;
      if (functionName != null) {
        functionNames.writeUnsigned(i);
        functionNames.writeName(functionName);
        functionNameCount++;
      }
    }

    int typeIndex = 0;
    int typeNameCount = 0;
    final typeNames = Serializer();
    int typesWithNamedFieldsCount = 0;
    final fieldNames = Serializer();
    for (final recursionGroup in types) {
      for (final defType in recursionGroup) {
        if (defType is ir.DataType) {
          final name = defType.name;
          if (name != null) {
            typeNames.writeUnsigned(typeIndex);
            typeNames.writeName(name);
            typeNameCount++;
            if (defType is ir.StructType && defType.fieldNames.isNotEmpty) {
              fieldNames.writeUnsigned(typeIndex);
              fieldNames.writeUnsigned(defType.fieldNames.length);
              for (final entry in defType.fieldNames.entries) {
                fieldNames.writeUnsigned(entry.key);
                fieldNames.writeName(entry.value);
              }
              typesWithNamedFieldsCount++;
            }
          }
        }
        typeIndex++;
      }
    }

    int globalNameCount = 0;
    final globalNames = Serializer();
    for (int i = 0; i < globals.length; i++) {
      final globalName = globals[i].globalName;
      if (globalName != null) {
        globalNames.writeUnsigned(i);
        globalNames.writeName(globalName);
        globalNameCount++;
      }
    }

    int functionsWithLocalNamesCount = 0;
    final localNames = Serializer();
    for (final function in functions) {
      if (function is ir.DefinedFunction) {
        if (function.localNames.isNotEmpty) {
          localNames.writeUnsigned(function.finalizableIndex.value);
          localNames.writeUnsigned(function.localNames.length);
          for (final entry in function.localNames.entries) {
            localNames.writeUnsigned(entry.key);
            localNames.writeName(entry.value);
          }
        }
      }
    }

    s.writeName("name"); // Name of the custom section.

    s.writeByte(0); // Module name subsection
    s.writeUnsigned(moduleNameSubsection.data.length);
    s.writeData(moduleNameSubsection);

    if (functionNameCount > 0) {
      s.writeByte(1); // Function names subsection
      s.writeUnsigned(functionNames.data.length +
          Serializer.writeUnsignedByteCount(functionNameCount));
      s.writeUnsigned(functionNameCount);
      s.writeData(functionNames);
    }

    if (functionsWithLocalNamesCount > 0) {
      s.writeByte(2); // Local names substion
      s.writeUnsigned(localNames.data.length +
          Serializer.writeUnsignedByteCount(functionsWithLocalNamesCount));
      s.writeUnsigned(functionsWithLocalNamesCount);
      s.writeData(localNames);
    }

    if (typeNameCount > 0) {
      s.writeByte(4); // Type names subsection
      s.writeUnsigned(typeNames.data.length +
          Serializer.writeUnsignedByteCount(typeNameCount));
      s.writeUnsigned(typeNameCount);
      s.writeData(typeNames);
    }

    if (globalNameCount > 0) {
      s.writeByte(7); // Global names subsection
      s.writeUnsigned(globalNames.data.length +
          Serializer.writeUnsignedByteCount(globalNameCount));
      s.writeUnsigned(globalNameCount);
      s.writeData(globalNames);
    }

    if (typesWithNamedFieldsCount > 0) {
      s.writeByte(10); // Field names subsection
      s.writeUnsigned(fieldNames.data.length +
          Serializer.writeUnsignedByteCount(typesWithNamedFieldsCount));
      s.writeUnsigned(typesWithNamedFieldsCount);
      s.writeData(fieldNames);
    }
  }
}

class SourceMapSection extends CustomSection {
  final Uri? url;

  SourceMapSection(this.url) : super([]);

  @override
  void serializeContents(Serializer s) {
    if (url != null) {
      s.writeName("sourceMappingURL");
      s.writeName(url!.toString());
    }
  }
}
