// Copyright (c) 2012, 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 serialization;

// TODO(alanknight): Figure out how to reasonably separate out the things
// that require reflection without making the API more awkward. Or if that is
// in fact necessary. Maybe the tree-shaking will just remove it if unused.

/**
 * This is the basic rule for handling "normal" objects, which have a list of
 * fields and a constructor, as opposed to simple types or collections. It uses
 * mirrors to access the state, and can also use them to figure out the list
 * of fields and the constructor if it's not provided.
 *
 * If you call [Serialization.addRule], this is what you get.
 *
 */
class BasicRule extends SerializationRule {
  /**
   * The [type] is used both to find fields and to verify if the object is one
   * that we handle.
   */
  final ClassMirror type;

  /** Used to create new objects when reading. */
  Constructor constructor;

  /** This holds onto our list of fields, and can also calculate them. */
  _FieldList _fields;

  /**
   * Instances can either use maps or lists to hold the object's state. The list
   * representation is much more compact and used by default. The map
   * representation is more human-readable. The default is to use lists.
   */
  bool useMaps = false;

  // TODO(alanknight) Change the type parameter once we have class literals.
  // Issue 6282.
  // TODO(alanknight) Does the comment for this format properly?
  /**
   * Create this rule. Right now the user is obliged to pass a ClassMirror,
   * but once we allow class literals (Issue 6282) it will support that. The
   * other parameters can all be left as null, and are optional on the
   * [Serialization.addRule] method which is the normal caller for this.
   * [constructorName] is the constructor, if not the default.
   * [constructorFields] are the fields required to call the constructor, which
   *   is the essential state. They don't have to be actual fields,
   *   getter/setter pairs or getter/constructor pairs are fine. Note that
   *   the constructorFields do not need to be strings, they can be arbitrary
   *   values. For non-strings, these will be treated as constant values to be
   *   used instead of data read from the objects.
   * [regularFields] are the non-essential fields. They don't have to be actual
   *   fields, getter/setter pairs are fine. If this is null, it's assumed
   *   that we should figure them out.
   * [excludeFields] lets you tell it to find the fields automatically, but
   *   omit some that would otherwise be included.
   */
  BasicRule(ClassMirror this.type, String constructorName,
      List constructorFields, List regularFields,
      List excludeFields) {
    _findFields(constructorFields, regularFields, excludeFields);
    constructor = new Constructor(
        type, constructorName, _fields.constructorFieldIndices());
    configureForLists();
  }

  /**
   * Sometimes it's necessary to treat fields of an object differently, based
   * on the containing object. For example, by default a list treats its
   * contents as non-essential state, so it will be populated only after all
   * objects have been created. An object may have a list which is used in its
   * constructor and must be fully created before the owning object can be
   * created. Alternatively, it may not be possible to set a field directly,
   * and some other method must be called to set it, perhaps calling a method
   * on the owning object to add each individual element.
   *
   * This method lets you designate a function to use to set the value of a
   * field. It also makes the contents of that field be treated as essential,
   * which currently only has meaning if the field is a list. This is done
   * because you might set a list field's special treatment function to add
   * each item individually and that will only work if those objects already
   * exist.
   *
   * For example, to serialize a Serialization, we need its rules to be
   * individually added rather than just setting the rules field.
   *      ..addRuleFor(new Serialization()).setFieldWith('rules',
   *          (InstanceMirror s, List rules) {
   *            rules.forEach((x) => s.reflectee.addRule(x));
   * Note that the function is passed the owning object as well as the field
   * value, but that it is passed as a mirror.
   */
  void setFieldWith(String fieldName, SetWithFunction setWith) {
    _fields.addAllByName([fieldName]);
    _NamedField field = _fields.named(_asSymbol(fieldName));
    Function setter = (setWith == null) ? field.defaultSetter : setWith;
    field.customSetter = setter;
  }

  /** Return the name of the constructor used to create new instances on read.*/
  String get constructorName => constructor.name;

  /** Return the list of field names to be passed to the constructor.*/
  List<String> get constructorFields => _fields.constructorFieldNames();

  /** Return the list of field names not used in the constructor. */
  List<String> get regularFields => _fields.regularFieldNames();

  String toString() => "Basic Rule for ${type.simpleName}";

  /**
   * Configure this instance to use maps by field name as its output.
   * Instances can either produce maps or lists. The list representation
   * is much more compact and used by default. The map representation is
   * much easier to debug. The default is to use lists.
   */
  void configureForMaps() {
    useMaps = true;
  }

  /**
   * Configure this instance to use lists accessing fields by index as its
   * output. Instances can either produce maps or lists. The list representation
   * is much more compact and used by default. The map representation is
   * much easier to debug. The default is to use lists.
   */
  void configureForLists() {
    useMaps = false;
  }

  /**
   * Create either a list or a map to hold the object's state, depending
   * on the [useMaps] variable. If using a Map, we wrap it in order to keep
   * the protocol compatible. See [configureForLists]/[configureForMaps].
   *
   * If a list is returned, it is growable.
   */
   createStateHolder() {
     if (useMaps) return new _MapWrapper(_fields.contents);
     List list = [];
     list.length = _fields.length;
     return list;
   }

  /**
   * Wrap the state if it's passed in as a map, and if the keys are references,
   * resolve them to the strings we expect. We leave the previous keys in there
   * as well, as they shouldn't be harmful, and it costs more to remove them.
   */
   makeIndexableByNumber(state) {
     if (!(state is Map)) return state;
     // TODO(alanknight): This is quite inefficient, and we do it twice per
     // instance. If the keys are references, we need to turn them into strings
     // before we can look at indexing them by field position. It's also eager,
     // but we know our keys are always primitives, so we don't have to worry
     // about their instances not having been created yet.
     var newState = new Map();
     for (var each in state.keys) {
       var newKey = (each is Reference) ? each.inflated() : each;
       newState[newKey] = state[each];
     }
     return new _MapWrapper.fromMap(newState, _fields.contents);
   }

  /**
   * Extract the state from [object] using an instanceMirror and the field
   * names in [_fields]. Call the function [callback] on each value.
   */
  extractState(object, Function callback, Writer w) {
    var result = createStateHolder();
    var mirror = reflect(object);

    keysAndValues(_fields).forEach(
        (index, field) {
          var value = _value(mirror, field);
          callback(field.name);
          callback(checkForEssentialLists(index, value));
          result[index] = value;
        });
    return _unwrap(result);
  }

  flatten(state, Writer writer) {
    if (state is List) {
      keysAndValues(state).forEach((index, value) {
        state[index] = writer._referenceFor(value);
      });
    } else {
      var newState = new Map();
      keysAndValues(state).forEach((key, value) {
        newState[writer._referenceFor(key)] = writer._referenceFor(value);
      });
      return newState;
    }
  }

  /**
   * If the value is a List, and the field is a constructor field or
   * otherwise specially designated, we wrap it in something that indicates
   * a restriction on the rules that can be used. Which in this case amounts
   * to designating the rule, since we so far only have one rule per object.
   */
  checkForEssentialLists(index, value) {
    if (value is List && _fields.contents[index].isEssential) {
      return new DesignatedRuleForObject(value,
          (SerializationRule rule) => rule is ListRuleEssential);
    } else {
      return value;
    }
  }

  /** Remove any MapWrapper from the extracted state. */
  _unwrap(result) => (result is _MapWrapper) ? result.asMap() : result;

  /**
   * Call the designated constructor with the appropriate fields from [state],
   * first resolving references in the context of [reader].
   */
  inflateEssential(state, Reader reader) {
    InstanceMirror mirror = constructor.constructFrom(
        makeIndexableByNumber(state), reader);
    return mirror.reflectee;
  }

  /** For all [rawState] not required in the constructor, set it in the
   * [object], resolving references in the context of [reader].
   */
  inflateNonEssential(rawState, object, Reader reader) {
    InstanceMirror mirror = reflect(object);
    var state = makeIndexableByNumber(rawState);
    _fields.forEachRegularField( (_Field field) {
      var value = reader.inflateReference(state[field.index]);
      field.setValue(mirror, value);
    });
  }

  /**
   * Determine if this rule applies to the object in question. In our case
   * this is true if the type mirrors are the same.
   */
  // TODO(alanknight): This seems likely to be slow. Verify. Other options?
  bool appliesTo(object, Writer w) => reflect(object).type == type;

  /**
   * Given the various field lists provided by the user, construct the list
   * of field names that we want.
   */
  void _findFields(List constructorFields, List regularFields,
      List excludeFields) {
    _fields = new _FieldList(type);
    _fields.constructorFields = constructorFields;
    _fields.regular = regularFields;
    // TODO(alanknight): The order of this matters. It shouldn't.
    _fields.exclude = excludeFields;
    _fields.figureOutFields();
  }

  bool get hasVariableLengthEntries => false;

  int get dataLength => _fields.length;

  /**
   * Extract the value of [field] from the object reflected
   * by [mirror].
   */
  // TODO(alanknight): The framework should be resilient if there are fields
  // it expects that are missing, either for the case of de-serializing to a
  // different definition, or for the case that tree-shaking has removed state.
  // TODO(alanknight): This, and other places, rely on synchronous access to
  // mirrors. Should be changed to use a synchronous API once one is available,
  // or to be async, but that would be extremely ugly.
  _value(InstanceMirror mirror, _Field field) => field.valueIn(mirror);
}

/**
 * This represents a field in an object. It is intended to be used as part of
 * a [_FieldList].
 */
abstract class _Field implements Comparable<_Field> {

  /** The FieldList that contains us. */
  final _FieldList fieldList;

  /**
   * Our position in the [fieldList._contents] collection. This is used
   * to index into the state, so it's extremely important.
   */
  int index;

  /** Is this field used in the constructor? */
  bool usedInConstructor = false;

  /**
   * Create a new [_Field] instance. This will be either a [_NamedField] or a
   * [_ConstantField] depending on whether or not [value] corresponds to a
   * field in the class which [fieldList] models.
   */
  factory _Field(value, _FieldList fieldList) {
    if (_isReallyAField(value, fieldList)) {
      return new _NamedField._internal(value, fieldList);
    } else {
      return new _ConstantField._internal(value, fieldList);
    }
  }

  /**
   * Determine if [value] represents a field or getter in the class that
   * [fieldList] models.
   */
  static bool _isReallyAField(value, _FieldList fieldList) {
    var symbol = _asSymbol(value);
    return hasField(symbol, fieldList.mirror) ||
        hasGetter(symbol, fieldList.mirror);
  }

  /** Private constructor. */
  _Field._internal(this.fieldList);

  /**
   * Extracts the value for the field that this represents from the instance
   * mirrored by [mirror] and return it.
   */
  valueIn(InstanceMirror mirror);

  // TODO(alanknight): Is this the right name, or is it confusing that essential
  // is not the inverse of regular.
  /** Return true if this is field is not used in the constructor. */
  bool get isRegular => !usedInConstructor;

  /**
   * Return true if this field is treated as essential state, either because
   * it is used in the constructor, or because it's been designated
   * using [BasicRule.setFieldWith].
   */
  bool get isEssential => usedInConstructor;

  /** Set the [value] of our field in the given mirrored [object]. */
  void setValue(InstanceMirror object, value);

  // Because [x] may not be a named field, we compare the toString. We don't
  // care that much where constants come in the sort order as long as it's
  // consistent.
  int compareTo(_Field x) => toString().compareTo(x.toString());
}

/**
 * This represents a field in the object, either stored as a field or
 * accessed via getter/setter/constructor parameter. It has a name and
 * will attempt to access the state for that name using an [InstanceMirror].
 */
class _NamedField extends _Field {
  /** The name of the field (or getter) */
  String _name;
  Symbol nameSymbol;

  /**
   * If this is set, then it is used as a way to set the value rather than
   * using the default mechanism.
   */
  Function customSetter;

  _NamedField._internal(fieldName, fieldList) : super._internal(fieldList) {
    nameSymbol = _asSymbol(fieldName);
    if (nameSymbol == null) {
      throw new SerializationException("Invalid field name $fieldName");
    }
  }

  String get name =>
      _name == null ? _name = MirrorSystem.getName(nameSymbol) : _name;

  operator ==(x) => x is _NamedField && (nameSymbol == x.nameSymbol);
  int get hashCode => name.hashCode;

  /**
   * Return true if this field is treated as essential state, either because
   * it is used in the constructor, or because it's been designated
   * using [BasicRule.setFieldWith].
   */
  bool get isEssential => super.isEssential || customSetter != null;

  /** Set the [value] of our field in the given mirrored [object]. */
  void setValue(InstanceMirror object, value) {
    setter(object, value);
  }

  valueIn(InstanceMirror mirror) => mirror.getField(nameSymbol).reflectee;

  /** Return the function to use to set our value. */
  Function get setter =>
      (customSetter != null) ? customSetter : defaultSetter;

  /** The default setter function. */
  void defaultSetter(InstanceMirror object, value) {
    object.setField(nameSymbol, value);
  }

  String toString() => 'Field($name)';
}

/**
 * This represents a constant value that will be passed as a constructor
 * parameter. Rather than having a name it has a constant value.
 */
class _ConstantField extends _Field {

  /** The value we always return.*/
  final value;

  _ConstantField._internal(this.value, fieldList) : super._internal(fieldList);

  operator ==(x) => x is _ConstantField && (value == x.value);
  int get hashCode => value.hashCode;
  String toString() => 'ConstantField($value)';
  valueIn(InstanceMirror mirror) => value;

  /** We cannot be set, so setValue is a no-op. */
  void setValue(InstanceMirror object, value) {}

  /** There are places where the code expects us to have an identifier, so
   * use the value for that.
   */
  get name => value;
}

/**
 * The organization of fields in an object can be reasonably complex, so they
 * are kept in a separate object, which also has the ability to compute the
 * default fields to use reflectively.
 */
class _FieldList extends IterableBase<_Field> {
  /**
   * All of our fields, indexed by name. Note that the names are
   * typically Symbols, but can also be arbitrary constants.
   */
  Map<dynamic, _Field> allFields = new Map<dynamic, _Field>();

  /**
   * The fields which are used in the constructor. The fields themselves also
   * know if they are constructor fields or not, but we need to keep this
   * information here because the order matters.
   */
  List _constructorFields = const [];

  /** The list of fields to exclude if we are computing the list ourselves. */
  List<Symbol> _excludedFieldNames = const [];

  /** The mirror we will use to compute the fields. */
  final ClassMirror mirror;

  /** Cached, sorted list of fields. */
  List<_Field> _contents;

  /** Should we compute the fields or just use whatever we were given. */
  bool _shouldFigureOutFields = true;

  _FieldList(this.mirror);

  /** Look up a field by [name]. */
  _Field named(name) => allFields[name];

  /** Set the fields to be used in the constructor. */
  set constructorFields(List fieldNames) {
    if (fieldNames == null || fieldNames.isEmpty) return;
    _constructorFields = [];
    for (var each in fieldNames) {
      var symbol = _asSymbol(each);
      var name = _Field._isReallyAField(symbol, this) ? symbol : each;
      var field = new _Field(name, this)..usedInConstructor = true;
      allFields[name] = field;
      _constructorFields.add(field);
    }
    invalidate();
  }

  /** Set the fields that aren't used in the constructor. */
  set regular(List<String> fields) {
    if (fields == null) return;
    _shouldFigureOutFields = false;
    addAllByName(fields);
  }

  /** Set the fields to be excluded. This is mutually exclusive with setting
   * the regular fields.
   */
  set exclude(List<String> fields) {
    // TODO(alanknight): This isn't well tested.
    if (fields == null || fields.isEmpty) return;
    if (allFields.length > _constructorFields.length) {
      throw "You can't specify both excludeFields and regular fields";
    }
    _excludedFieldNames = fields.map((x) => new Symbol(x)).toList();
  }

  int get length => allFields.length;

  /** Add all the fields which aren't on the exclude list. */
  void addAllNotExplicitlyExcluded(Iterable<String> aCollection) {
    if (aCollection == null) return;
    var names = aCollection;
    names = names.where((x) => !_excludedFieldNames.contains(x));
    addAllByName(names);
  }

  /** Add all the fields with the given names without any special properties. */
  void addAllByName(Iterable<String> names) {
    for (var each in names) {
      var symbol = _asSymbol(each);
      var field = new _Field(symbol, this);
      allFields.putIfAbsent(symbol, () => new _Field(symbol, this));
    }
    invalidate();
  }

  /**
   * Fields have been added. In case we had already forced calculation of the
   * list of contents, re-set it.
   */
  void invalidate() {
    _contents = null;
    contents;
  }

  Iterator<_Field> get iterator => contents.iterator;

  /** Return a cached, sorted list of all the fields. */
  List<_Field> get contents {
    if (_contents == null) {
      _contents = sorted(allFields.values);
      for (var i = 0; i < _contents.length; i++)
        _contents[i].index = i;
    }
    return _contents;
  }

  /** Iterate over the regular fields, i.e. those not used in the constructor.*/
  void forEachRegularField(Function f) {
    for (var each in contents) {
      if (each.isRegular) {
        f(each);
      }
    }
  }

  /** Iterate over the fields used in the constructor. */
  void forEachConstructorField(Function f) {
    for (var each in contents) {
      if (each.usedInConstructor) {
        f(each);
      }
    }
  }

  List get constructorFields => _constructorFields;
  List constructorFieldNames() =>
      constructorFields.map((x) => x.name).toList();
  List constructorFieldIndices() =>
      constructorFields.map((x) => x.index).toList();
  List regularFields() => contents.where((x) => !x.usedInConstructor).toList();
  List regularFieldNames() => regularFields().map((x) => x.name).toList();
  List regularFieldIndices() =>
      regularFields().map((x) => x.index).toList();

  /**
   * If we weren't given any non-constructor fields to use, figure out what
   * we think they ought to be, based on the class definition.
   * We find public fields, getters that have corresponding setters, and getters
   * that are listed in the constructor fields.
   */
  void figureOutFields() {
    Iterable names(Iterable<DeclarationMirror> mirrors) =>
        mirrors.map((each) => each.simpleName).toList();

    if (!_shouldFigureOutFields || !regularFields().isEmpty) return;
    var fields = publicFields(mirror);
    var getters = publicGetters(mirror);
    var gettersWithSetters = getters.where( (each)
        => mirror.setters[
            new Symbol("${MirrorSystem.getName(each.simpleName)}=")] != null);
    var gettersThatMatchConstructor = getters.where((each)
        => (named(each.simpleName) != null) &&
            (named(each.simpleName).usedInConstructor)).toList();
    addAllNotExplicitlyExcluded(names(fields));
    addAllNotExplicitlyExcluded(names(gettersWithSetters));
    addAllNotExplicitlyExcluded(names(gettersThatMatchConstructor));
  }

  toString() => "FieldList($contents)";
}

/**
 *  Provide a typedef for the setWith argument to setFieldWith. It would
 * be nice if we could put this closer to the definition.
 */
typedef SetWithFunction(InstanceMirror m, object);

/**
 * This represents a constructor that is to be used when re-creating a
 * serialized object.
 */
class Constructor {
  /** The mirror of the class we construct. */
  final ClassMirror type;

  /** The name of the constructor to use, if not the default constructor.*/
  String name;
  Symbol nameSymbol;

  /**
   * The indices of the fields used as constructor arguments. We will look
   * these up in the state by number. The index is according to a list of the
   * fields in alphabetical order by name.
   */
  List<int> fieldNumbers;

  /**
   * Creates a new constructor for the [type] with the constructor named [name]
   * and the [fieldNumbers] of the constructor fields.
   */
  Constructor(this.type, this.name, this.fieldNumbers) {
    if (name == null) name = '';
    nameSymbol = new Symbol(name);
    if (fieldNumbers == null) fieldNumbers = const [];
  }

  /**
   * Find the field values in [state] and pass them to the constructor.
   * If any of [fieldNumbers] is not an int, then use it as a literal value.
   */
  constructFrom(state, Reader r) {
    // TODO(alanknight): Handle named parameters
    Iterable inflated = fieldNumbers.map(
        (x) => (x is int) ? r.inflateReference(state[x]) : x);
    var result;
    try {
      result = type.newInstance(nameSymbol, inflated.toList());
    } on MirroredError catch (e) {
      // Mirrored "compile-time" errors do not get treated as exceptions
      // in the debugger, so explicitly re-throw. Issue dartbug.com/10054.
      throw e;
    }
    return result;
  }
}

/**
 * This wraps a map to make it indexable by integer field numbers. It translates
 * from the index into a field name and then looks it up in the map.
 */
class _MapWrapper {
  final Map _map;
  final List fieldList;
  _MapWrapper(this.fieldList) : _map = new Map();
  _MapWrapper.fromMap(this._map, this.fieldList);

  operator [](key) => _map[fieldList[key].name];

  operator []=(key, value) { _map[fieldList[key].name] = value; }
  get length => _map.length;

  Map asMap() => _map;
}

/**
 * Return a symbol corresponding to [value], which may be a String or a
 * Symbol. If it is any other type, or if the string is an
 * invalid symbol, return null;
 */
Symbol _asSymbol(value) {
  if (value is Symbol) return value;
  if (value is String) {
    try {
      return new Symbol(value);
    } on ArgumentError {
      return null;
    };
  } else {
    return null;
  }
}