// Copyright (c) 2025, 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 '../banned_names.dart';
import 'qualified_name.dart';

class ID {
  final String type;
  final String name;
  final int? index;

  const ID({required this.type, required this.name, this.index});

  bool get isUnnamed => name == 'unnamed';

  String get rename {
    if (index != null && index != 0) {
      final s =
          name.endsWith(r'$') ? name.substring(0, name.indexOf(r'$')) : name;
      return '$s\$$index';
    } else {
      return name;
    }
  }

  @override
  String toString() => '$type#$name${index != null ? '#$index' : ''}';

  @override
  bool operator ==(Object other) {
    return other is ID &&
        other.name == name &&
        other.type == type &&
        other.index == index;
  }

  @override
  int get hashCode => Object.hash(type, name, index);
}

class UniqueNamer {
  final Set<String> _usedNames;

  Set<String> get used => _usedNames;

  UniqueNamer([
    Iterable<String> used = const <String>[],
  ]) : _usedNames = used.toSet();

  /// Makes a name that does not conflict with dart keywords
  static String makeNonConflicting(String name) {
    if (int.tryParse(name) != null) {
      return '\$$name';
    } else if (double.tryParse(name) != null) {
      return '\$${name.splitMapJoin(
        '.',
        onMatch: (p0) => 'dot',
      )}';
    } else if (keywords.contains(name)) {
      return '$name\$';
    } else {
      return name;
    }
  }

  /// Creates a unique name and ID for a given declaration to prevent
  /// name collisions in Dart applications
  ///
  /// (Dart does not support operator overloading)
  ({ID id, String name}) makeUnique(String name, String type) {
    // nested structures (and anonymous structures) may not have a name
    if (name.isEmpty) {
      name = 'unnamed';
    }

    var newName = UniqueNamer.makeNonConflicting(name);

    var i = 0;
    while (_usedNames.contains(newName)) {
      ++i;
      newName = '$name\$$i';
    }

    markUsed(newName);
    return (
      id: ID(type: type, name: name, index: i == 0 ? null : i),
      name: newName
    );
  }

  /// Adds names from scoped declarations to [_usedNames]
  void markUsedSet(ScopedUniqueNamer namer) {
    for (final ID(name: name, type: type) in namer._usedIDs) {
      if (['namespace', 'interface', 'class'].contains(type)) {
        final qualifiedName = QualifiedName.raw(name);
        // generate to completed name
        final indexedName = qualifiedName.join('_');
        markUsed(indexedName);
      }
    }
  }

  static ID parse(String id) {
    String? index;
    String name;
    final [type, ...parts] = id.split('#');
    if (parts.isEmpty) {
      throw Exception('Invalid ID: $id');
    } else {
      name = parts[0];
      if (parts.length > 1) index = parts[1];
    }

    return ID(
        type: type, name: name, index: index == null ? null : int.parse(index));
  }

  /// Adds a [name] to used names.
  void markUsed(String name, [String? type]) {
    _usedNames.add(name);
  }
}

class ScopedUniqueNamer implements UniqueNamer {
  final Set<ID> _usedIDs;
  final Set<String> _allowedEquals;

  @override
  Set<String> get _usedNames => _usedIDs.map((i) => i.rename).toSet();

  @override
  Set<String> get used => _usedNames;

  ScopedUniqueNamer(
      [Set<String>? allowedEquals, Iterable<String> used = const <String>[]])
      : _usedIDs = used.map(UniqueNamer.parse).toSet(),
        _allowedEquals = allowedEquals ?? {};

  @override
  ({ID id, String name}) makeUnique(String name, String type) {
    // nested structures (and anonymous structures) may not have a name

    final newName = UniqueNamer.makeNonConflicting(name);

    var i = 0;
    var id = ID(name: newName, type: type);
    while (_usedIDs.any((usedID) {
      if (usedID.name == id.name && usedID.index == id.index) {
        // check if both types are allowed
        if (_allowedEquals.contains(usedID.type) &&
            _allowedEquals.contains(id.type)) {
          return false;
        }
        return true;
      }
      return false;
    })) {
      ++i;
      id = ID(name: newName, index: i, type: type);
    }

    markUsed(id.toString());

    return (id: id, name: id.rename);
  }

  @override
  void markUsed(String name, [String? type]) {
    ID id;
    try {
      id = UniqueNamer.parse(name);
    } catch (e) {
      id = ID(type: type!, name: name);
    }

    _usedIDs.add(id);
  }

  @override
  void markUsedSet(ScopedUniqueNamer namer) {
    _usedIDs.addAll(namer._usedIDs);
  }
}
