// 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.
   */
  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.
   */
  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.
   */
  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.
  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 {
  /**
   * 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 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;
  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;

  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;
 */
_asSymbol(value) {
  if (value is Symbol) return value;
  if (value is String) {
    try {
      return new Symbol(value);
    } on ArgumentError {
      return null;
    };
  } else {
    return null;
  }
}