// Copyright (c) 2022, 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 'equal.dart';
import 'static_type.dart';

/// The main space for matching types and destructuring.
///
/// It has a type which determines the type of values it contains. The type may
/// be [StaticType.nullableObject] to indicate that it doesn't filter by type.
///
/// It may also contain zero or more named fields. The space then only contains
/// values where the field values are contained by the corresponding field
/// spaces.
class ExtractSpace extends Space {
  /// The type of values the space matches.
  final StaticType type;

  /// Any field subspaces the space matches.
  final Map<String, Space> fields;

  ExtractSpace._(this.type, [this.fields = const {}]) : super._();

  /// An [ExtractSpace] with no type and no fields contains all values.
  @override
  bool get isTop => type == StaticType.nullableObject && fields.isEmpty;

  @override
  String toString() {
    if (isTop) return '()';
    if (this == Space.empty) return '∅';

    // If there are no fields, just show the type.
    if (fields.isEmpty) return type.name;

    StringBuffer buffer = new StringBuffer();

    // We model a bare record pattern by treating it like an extractor on top.
    if (type != StaticType.nonNullableObject) buffer.write(type.name);

    buffer.write('(');
    bool first = true;

    // Positional fields have stringified number names.
    for (int i = 0;; i++) {
      Space? pattern = fields[i.toString()];
      if (pattern == null) break;

      if (!first) buffer.write(', ');
      buffer.write(pattern);
      first = false;
    }

    fields.forEach((name, pattern) {
      // Skip positional fields.
      if (int.tryParse(name) != null) return;

      if (!first) buffer.write(', ');
      buffer.write('$name: $pattern');
      first = false;
    });

    buffer.write(')');

    return buffer.toString();
  }
}

// TODO(paulberry, rnystrom): List spaces.

abstract class Space {
  /// The uninhabited space.
  static final Space empty = new Space(StaticType.neverType);

  /// The space containing everything.
  static final Space top = new Space(StaticType.nullableObject);

  factory Space(StaticType type, [Map<String, Space> fields = const {}]) =>
      new ExtractSpace._(type, fields);

  factory Space.record([Map<String, Space> fields = const {}]) =>
      new Space(StaticType.nonNullableObject, fields);

  factory Space.union(List<Space> arms) {
    // Simplify the arms if possible.
    List<ExtractSpace> allArms = <ExtractSpace>[];

    void addSpace(ExtractSpace space) {
      // Discard duplicate arms. Duplicates can appear when working through a
      // series of cases that destructure multiple fields with different types.
      // Discarding the duplicates isn't necessary for correctness (a union with
      // redundant arms contains the same set of values), but improves
      // performance greatly. In the "sealed subtypes large T with all cases"
      // test, you end up with a union containing 2520 arms, 2488 are
      // duplicates. With this check, the largest union has only 5 arms.
      //
      // This is O(n^2) since we define only equality on spaces, but a real
      // implementation would likely define hash code too and then simply
      // create a hash set to merge duplicates in O(n) time.
      for (Space existing in allArms) {
        if (equal(existing, space, 'dedupe union')) return;
      }

      allArms.add(space);
    }

    for (Space space in arms) {
      // Discard empty arms.
      if (space == empty) continue;

      // Flatten unions. We don't need to flatten recursively since we always
      // go through this constructor to create unions. A UnionSpace will never
      // contain UnionSpaces.
      if (space is UnionSpace) {
        for (ExtractSpace arm in space.arms) {
          addSpace(arm);
        }
      } else {
        addSpace(space as ExtractSpace);
      }
    }

    if (allArms.isEmpty) return empty;
    if (allArms.length == 1) return allArms.first;
    if (allArms.length == 2) {
      if (allArms[0].type == StaticType.nullType &&
          allArms[0].fields.isEmpty &&
          allArms[1].fields.isEmpty) {
        return new Space(allArms[1].type.nullable);
      } else if (allArms[1].type == StaticType.nullType &&
          allArms[1].fields.isEmpty &&
          allArms[0].fields.isEmpty) {
        return new Space(allArms[0].type.nullable);
      }
    }
    return new UnionSpace._(allArms);
  }

  Space._();

  /// An untyped record space with no fields matches all values and thus isn't
  /// very useful.
  bool get isTop => false;
}

/// A union of spaces. The space A|B contains all of the values of A and B.
class UnionSpace extends Space {
  final List<ExtractSpace> arms;

  UnionSpace._(this.arms) : super._() {
    assert(arms.length > 1);
  }

  @override
  String toString() => arms.join('|');
}
