// Copyright (c) 2024, 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 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;

class TryBlock {
  static const int flagNeedsStackTrace = 1 << 0;
  static const int flagIsSynthetic = 1 << 1;

  final int tryIndex;
  final int outerTryIndex;
  final int startPC;
  int endPC = -1;
  int handlerPC = -1;
  int flags = 0;
  List<int> types = <int>[];

  TryBlock._(this.tryIndex, this.outerTryIndex, this.startPC);

  bool get needsStackTrace => (flags & flagNeedsStackTrace) != 0;

  void set needsStackTrace(bool value) {
    flags = (flags & ~flagNeedsStackTrace) | (value ? flagNeedsStackTrace : 0);
  }

  bool get isSynthetic => (flags & flagIsSynthetic) != 0;

  void set isSynthetic(bool value) {
    flags = (flags & ~flagIsSynthetic) | (value ? flagIsSynthetic : 0);
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(outerTryIndex + 1);
    writer.writePackedUInt30(startPC);
    writer.writePackedUInt30(endPC);
    writer.writePackedUInt30(handlerPC);
    writer.writeByte(flags);
    writer.writePackedUInt30(types.length);
    types.forEach(writer.writePackedUInt30);
  }

  factory TryBlock.read(BufferedReader reader, int tryIndex) {
    final outerTryIndex = reader.readPackedUInt30() - 1;
    final startPC = reader.readPackedUInt30();
    final tryBlock = new TryBlock._(tryIndex, outerTryIndex, startPC);

    tryBlock.endPC = reader.readPackedUInt30();
    tryBlock.handlerPC = reader.readPackedUInt30();
    tryBlock.flags = reader.readByte();
    tryBlock.types = new List<int>.generate(
      reader.readPackedUInt30(),
      (_) => reader.readPackedUInt30(),
    );

    return tryBlock;
  }

  @override
  String toString() =>
      'try-index $tryIndex, outer $outerTryIndex, '
      'start $startPC, end $endPC, handler $handlerPC, '
      '${needsStackTrace ? 'needs-stack-trace, ' : ''}'
      '${isSynthetic ? 'synthetic, ' : ''}'
      'types ${types.map((t) => 'CP#$t').toList()}';
}

class ExceptionsTable {
  List<TryBlock> blocks = <TryBlock>[];

  ExceptionsTable();

  TryBlock enterTryBlock(int startPC) {
    assert(blocks.isEmpty || blocks.last.startPC <= startPC);
    final tryBlock = new TryBlock._(
      blocks.length,
      _outerTryBlockIndex(startPC),
      startPC,
    );
    blocks.add(tryBlock);
    return tryBlock;
  }

  int _outerTryBlockIndex(int startPC) {
    for (int i = blocks.length - 1; i >= 0; --i) {
      final tryBlock = blocks[i];
      if (tryBlock.endPC < 0 || tryBlock.endPC > startPC) {
        return i;
      }
    }
    return -1;
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(blocks.length);
    blocks.forEach((b) => b.write(writer));
  }

  ExceptionsTable.read(BufferedReader reader)
    : blocks = new List<TryBlock>.generate(
        reader.readPackedUInt30(),
        (int index) => new TryBlock.read(reader, index),
      );

  @override
  String toString() {
    if (blocks.isEmpty) {
      return '';
    }
    StringBuffer sb = new StringBuffer();
    sb.writeln('ExceptionsTable {');
    for (var tryBlock in blocks) {
      sb.writeln('  $tryBlock');
    }
    sb.writeln('}');
    return sb.toString();
  }
}
