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

/// Provides metadata about mixins to dart-protoc-plugin.
/// (Experimental API; subject to change.)
import 'indenting_writer.dart';

/// Finds [name] in the exported mixins.
PbMixin findMixin(String name) {
  const _exportedMixins = {
    'PbMapMixin': _pbMapMixin,
    'PbEventMixin': _pbEventMixin,
  };
  return _exportedMixins[name];
}

/// PbMixin contains metadata needed by dart-protoc-plugin to apply a mixin.
///
/// The mixin can be applied to a message using options in dart_options.proto.
/// Only one mixin can be applied to each message, but that mixin can depend
/// on another mixin, recursively, similar to single inheritance.
class PbMixin {
  /// The name of the mixin class to import into the .pb.dart file.
  final String name;

  /// The file that the .pb.dart file should import the symbol from.
  final String importFrom;

  /// Another mixin to apply ahead of this one, or null for none.
  final PbMixin parent;

  /// Names that shouldn't be used by properties in the generated child class.
  /// May be null if the mixin doesn't reserve any new names.
  final List<String> reservedNames;

  /// Code to inject into the class using the mixin.
  ///
  /// Typically used for static helpers since you cannot mix in static members.
  final List<String> injectedHelpers;

  /// If `True` the mixin should have static methods for converting to and from
  /// proto3 Json.
  final bool hasProto3JsonHelpers;

  const PbMixin(
    this.name, {
    this.importFrom,
    this.parent,
    this.reservedNames,
    this.injectedHelpers,
    this.hasProto3JsonHelpers = false,
  });

  /// Returns the mixin and its ancestors, in the order they should be applied.
  Iterable<PbMixin> findMixinsToApply() {
    var result = [this];
    for (var p = parent; p != null; p = p.parent) {
      result.add(p);
    }
    return result.reversed;
  }

  /// Returns all the reserved names, including from ancestor mixins.
  Iterable<String> findReservedNames() {
    var names = <String>{};
    for (var m = this; m != null; m = m.parent) {
      names.add(m.name);
      if (m.reservedNames != null) {
        names.addAll(m.reservedNames);
      }
    }
    return names;
  }

  void injectHelpers(IndentingWriter out) {
    if (injectedHelpers != null && injectedHelpers.isNotEmpty) {
      out.println(injectedHelpers.join('\n'));
    }
  }
}

const _pbMapMixin = PbMixin("PbMapMixin",
    importFrom: "package:protobuf/src/protobuf/mixins/map_mixin.dart",
    parent: _mapMixin);

const _pbEventMixin = PbMixin("PbEventMixin",
    importFrom: "package:protobuf/src/protobuf/mixins/event_mixin.dart",
    reservedNames: ["changes", "deliverChanges"]);

const List<String> _reservedNamesForMap = [
  '[]',
  '[]=',
  'addAll',
  'addEntries',
  'cast',
  'containsKey',
  'containsValue',
  'entries',
  'forEach',
  'isEmpty',
  'isNotEmpty',
  'keys',
  'length',
  'map',
  'putIfAbsent',
  'remove',
  'removeWhere',
  'retype',
  'update',
  'updateAll',
  'values',
];

const _mapMixin = PbMixin("MapMixin",
    importFrom: "dart:collection", reservedNames: _reservedNamesForMap);
