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

part of js_backend.namer;

abstract class _NamerName extends jsAst.Name {
  int get _kind;

  @override
  _NamerName withSourceInformation(
      jsAst.JavaScriptNodeSourceInformation? newSourceInformation) {
    if (sourceInformation == newSourceInformation) return this;
    final name = this; // Variable needed for type promotion in next line.
    final underlying = name is _NameReference ? name._target : this;
    return _NameReference(underlying, newSourceInformation);
  }

  int _compareSameKind(covariant _NamerName);

  @override
  String toString() {
    if (DEBUG_MODE) {
      return 'Name($key)';
    }
    throw UnsupportedError("Cannot convert a name to a string");
  }
}

enum _NamerNameKinds { StringBacked, Getter, Setter, Async, Compound, Token }

/// An arbitrary but stable sorting comparison method.
int compareNames(jsAst.Name aName, jsAst.Name bName) {
  _NamerName dereference(jsAst.Name name) {
    if (name is ModularName) return dereference(name.value);
    if (name is _NameReference) return dereference(name._target);
    if (name is _NamerName) return name;
    throw UnsupportedError('Cannot find underlying _NamerName: $name');
  }

  _NamerName a = dereference(aName);
  _NamerName b = dereference(bName);

  int aKind = a._kind;
  int bKind = b._kind;
  if (bKind != aKind) return bKind - aKind;
  return a._compareSameKind(b);
}

class StringBackedName extends _NamerName {
  @override
  final String name;
  @override
  int get _kind => _NamerNameKinds.StringBacked.index;

  StringBackedName(this.name);

  @override
  String get key => name;

  @override
  operator ==(Object other) {
    if (other is _NameReference) return this == other._target;
    if (identical(this, other)) return true;
    return other is StringBackedName && name == other.name;
  }

  @override
  int get hashCode => name.hashCode;

  @override
  int _compareSameKind(StringBackedName other) {
    return name.compareTo(other.name);
  }
}

abstract class _PrefixedName extends _NamerName implements jsAst.AstContainer {
  final jsAst.Name prefix;
  final jsAst.Name base;
  @override
  int get _kind;

  @override
  Iterable<jsAst.Node> get containedNodes => [prefix, base];

  _PrefixedName(this.prefix, this.base);

  @override
  String get name => prefix.name + base.name;

  @override
  String get key => prefix.key + base.key;

  @override
  bool operator ==(Object other) {
    if (other is _NameReference) return this == other._target;
    if (identical(this, other)) return true;
    return other is _PrefixedName &&
        base == other.base &&
        prefix == other.prefix;
  }

  @override
  int get hashCode => base.hashCode * 13 + prefix.hashCode;

  @override
  bool get isFinalized => prefix.isFinalized && base.isFinalized;

  @override
  int _compareSameKind(_PrefixedName other) {
    int result = compareNames(prefix, other.prefix);
    if (result == 0) {
      result = compareNames(base, other.base);
    }
    return result;
  }
}

class GetterName extends _PrefixedName {
  @override
  int get _kind => _NamerNameKinds.Getter.index;

  GetterName(super.prefix, super.base);
}

class SetterName extends _PrefixedName {
  @override
  int get _kind => _NamerNameKinds.Setter.index;

  SetterName(super.prefix, super.base);
}

class AsyncName extends _PrefixedName {
  @override
  int get _kind => _NamerNameKinds.Async.index;

  AsyncName(super.prefix, super.base);

  @override
  bool get allowRename => true;
}

class CompoundName extends _NamerName implements jsAst.AstContainer {
  final List<_NamerName> _parts;
  @override
  int get _kind => _NamerNameKinds.Compound.index;
  int _cachedHashCode = -1;

  @override
  Iterable<jsAst.Node> get containedNodes => _parts;

  CompoundName(this._parts);

  CompoundName.from(List<_NamerName> parts) : this([...parts]);

  @override
  bool get isFinalized => _parts.every((name) => name.isFinalized);

  @override
  late final String name = _parts.map((jsAst.Name name) => name.name).join();

  @override
  String get key => _parts.map((_NamerName name) => name.key).join();

  @override
  bool operator ==(Object other) {
    if (other is _NameReference) return this == other._target;
    if (identical(this, other)) return true;
    if (other is CompoundName) {
      if (other._parts.length != _parts.length) return false;
      for (int i = 0; i < _parts.length; ++i) {
        if (_parts[i] != other._parts[i]) return false;
      }
      return true;
    }
    return false;
  }

  @override
  int get hashCode {
    if (_cachedHashCode < 0) {
      _cachedHashCode = 0;
      for (jsAst.Name name in _parts) {
        _cachedHashCode = (_cachedHashCode * 17 + name.hashCode) & 0x7fffffff;
      }
    }
    return _cachedHashCode;
  }

  @override
  int _compareSameKind(CompoundName other) {
    int result = _parts.length.compareTo(other._parts.length);
    for (int pos = 0; result == 0 && pos < _parts.length; pos++) {
      result = compareNames(_parts[pos], other._parts[pos]);
    }
    return result;
  }
}

class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
  @override
  int get _kind => _NamerNameKinds.Token.index;
  String? _name;
  @override
  final String key;
  final TokenScope _scope;
  int _rc = 0;

  TokenName(this._scope, this.key);

  @override
  bool get isFinalized => _name != null;

  @override
  String get name => _name!;

  @override
  int _compareSameKind(TokenName other) {
    return key.compareTo(other.key);
  }

  @override
  void markSeen(jsAst.TokenCounter counter) => _rc++;

  @override
  bool operator ==(Object other) {
    if (other is _NameReference) return this == other._target;
    if (identical(this, other)) return true;
    return false;
  }

  @override
  int get hashCode => super.hashCode;

  void finalize() {
    assert(
        !isFinalized,
        failedAt(NO_LOCATION_SPANNABLE,
            "TokenName($key)=$_name has already been finalized."));
    _name = _scope.getNextName();
  }
}

/// A [_NameReference] behaves like the underlying (target) [_NamerName] but
/// carries its own [JavaScriptNodeSourceInformation].
// TODO(sra): See if this functionality can be moved into js_ast.
class _NameReference extends _NamerName implements jsAst.AstContainer {
  final _NamerName _target;
  final jsAst.JavaScriptNodeSourceInformation? _sourceInformation;

  _NameReference(this._target, this._sourceInformation);

  @override
  jsAst.JavaScriptNodeSourceInformation? get sourceInformation =>
      _sourceInformation;

  @override
  int get _kind => _target._kind;
  @override
  String get key => _target.key;

  @override
  Iterable<jsAst.Node> get containedNodes => [_target];

  @override
  String get name => _target.name;

  @override
  int _compareSameKind(_NameReference other) {
    throw StateError('Should have been dereferenced: $this');
  }

  @override
  bool get isFinalized => _target.isFinalized;

  @override
  bool operator ==(Object other) => _target == other;

  @override
  int get hashCode => _target.hashCode;
}
