// 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): We should have an example and tests for subclassing
// serialization rule rather than using the hard-coded ClosureToMap rule. And
// possibly an abstract superclass that's designed to be subclassed that way.
/**
 * The abstract superclass for serialization rules.
 */
abstract class SerializationRule {
  /**
   * Rules belong uniquely to a particular Serialization instance, and can
   * be identified within it by number.
   */
  int _number;

  /**
   * Rules belong uniquely to a particular Serialization instance, and can
   * be identified within it by number.
   */
  int get number => _number;

  /**
   * Rules belong uniquely to a particular Serialization instance, and can
   * be identified within it by number.
   */
  void set number(int value) {
    if (_number != null && _number != value) throw
        new SerializationException("Rule numbers cannot be changed, once set");
    _number = value;
  }

  /**
   * Return true if this rule applies to this object, in the context
   * where we're writing it, false otherwise.
   */
  bool appliesTo(object, Writer writer);

  /**
   * This extracts the state from the object, calling [f] for each value
   * as it is extracted, and returning an object representing the whole
   * state at the end. The state that results will still have direct
   * pointers to objects, rather than references.
   */
  extractState(object, void f(value), Writer w);

  /**
   * Allows rules to tell us how they expect to store their state. If this
   * isn't specified we can also just look at the data to tell.
   */
  bool get storesStateAsLists => false;
  bool get storesStateAsMaps => false;
  bool get storesStateAsPrimitives => false;

  /**
   * Given the variables representing the state of an object, flatten it
   * by turning object pointers into Reference objects where needed. This
   * destructively modifies the state object.
   *
   * This has a default implementation which assumes that object is indexable,
   * so either conforms to Map or List. Subclasses may override to do something
   * different, including returning a new state object to be used in place
   * of the original.
   */
  // This has to be a separate operation from extracting, because we extract
  // as we are traversing the objects, so we don't yet have the objects to
  // generate references for them. It might be possible to avoid that by
  // doing a depth-first rather than breadth-first traversal, but I'm not
  // sure it's worth it.
  flatten(state, Writer writer) {
    keysAndValues(state).forEach((key, value) {
      var reference = writer._referenceFor(value);
      state[key] = reference;
    });
  }

  /** Return true if this rule should only be applied when we are the first
   * rule found that applies to this object. This may or may not be a hack
   * that will disappear once we have better support for multiple rules.
   * We want to have multiple different rules that apply to the same object. We
   * also want to have multiple different rules that might exclusively apply
   * to the same object. So, we want either ListRule or ListRuleEssential, and
   * only one of them can be there. But on the other hand, we may want both
   * ListRule and BasicRule. So we identify the kinds of rules that can share.
   * If mustBePrimary returns true, then this rule will only be chosen if no
   * other rule has been found yet. This means that the ordering of rules in
   * the serialization is significant, which is unpleasant, but we'll have
   * to see how bad it is.
   */
  // TODO(alanknight): Reconsider whether this should be handled differently.
  bool get mustBePrimary => false;

  /**
   * Create the new object corresponding to [state] using the rules
   * from [reader]. This may involve recursively inflating "essential"
   * references in the state, which are those that are required for the
   * object's constructor. It is up to the rule what state is considered
   * essential.
   */
  inflateEssential(state, Reader reader);

  /**
   * The [object] has already been created. Set any of its non-essential
   * variables from the representation in [state]. Where there are references
   * to other objects they are resolved in the context of [reader].
   */
  inflateNonEssential(state, object, Reader reader);

  /**
   * If we have [object] as part of our state, should we represent that
   * directly, or should we make a reference for it. By default, true.
   * This may also delegate to [writer].
   */
  bool shouldUseReferenceFor(object, Writer writer) => true;

  /**
   * Return true if the data this rule returns is variable length, so a
   * length needs to be written for it if the format requires that. Return
   * false if the results are always the same length.
   */
  bool get hasVariableLengthEntries => true;

  /**
   * If the data is fixed length, return it here. The format may or may not
   * make use of this, depending on whether it already has enough information
   * to determine the length on its own. If [hasVariableLengthEntries] is true
   * this is ignored.
   */
  int get dataLength => 0;
}

/**
 * This rule handles things that implement List. It will recreate them as
 * whatever the default implemenation of List is on the target platform.
 */
class ListRule extends SerializationRule {

  bool appliesTo(object, Writer w) => object is List;

  bool get storesStateAsLists => true;

  List extractState(List list, f, Writer w) {
    var result = new List();
    for (var each in list) {
      result.add(each);
      f(each);
    }
    return result;
  }

  inflateEssential(List state, Reader r) => new List();

  // For a list, we consider all of its state non-essential and add it
  // after creation.
  inflateNonEssential(List state, List newList, Reader r) {
    populateContents(state, newList, r);
  }

  void populateContents(List state, List newList, Reader r) {
    for(var each in state) {
      newList.add(r.inflateReference(each));
    }
  }

  bool get hasVariableLengthEntries => true;
}

/**
 * This is a subclass of ListRule where all of the list's contents are
 * considered essential state. This is needed if an object X contains a List L,
 * but it expects L's contents to be fixed when X's constructor is called.
 */
class ListRuleEssential extends ListRule {

  /** Create the new List and also inflate all of its contents. */
  inflateEssential(List state, Reader r) {
    var object = super.inflateEssential(state, r);
    populateContents(state, object, r);
    return object;
  }

  /** Does nothing, because all the work has been done in inflateEssential. */
  inflateNonEssential(state, newList, reader) {}

  bool get mustBePrimary => true;
}

/**
 * This rule handles things that implement Map. It will recreate them as
 * whatever the default implemenation of Map is on the target platform. If a
 * map has string keys it will attempt to retain it as a map for JSON formats,
 * otherwise it will store it as a list of references to keys and values.
 */
class MapRule extends SerializationRule {

  bool appliesTo(object, Writer w) => object is Map;

  bool get storesStateAsMaps => true;

  extractState(Map map, f, Writer w) {
    // Note that we make a copy here because flattening may be destructive.
    var newMap = new Map.from(map);
    newMap.forEach((key, value) {
      f(key);
      f(value);
    });
    return newMap;
  }

  /**
   * Change the keys and values of [state] into references in [writer].
   * If [state] is a map whose keys are all strings then we leave the keys
   * as is so that JSON formats will be more readable. If the keys are
   * arbitrary then we need to turn them into references and replace the
   * state with a new Map whose keys are the references.
   */
  flatten(Map state, Writer writer) {
    bool keysAreAllStrings = state.keys.every((x) => x is String);
    if (keysAreAllStrings && !writer.shouldUseReferencesForPrimitives) {
      keysAndValues(state).forEach(
          (key, value) => state[key] = writer._referenceFor(value));
      return state;
    } else {
      var newState = [];
      keysAndValues(state).forEach((key, value) {
        newState.add(writer._referenceFor(key));
        newState.add(writer._referenceFor(value));
      });
      return newState;
    }
  }

  inflateEssential(state, Reader r) => new Map();

  // For a map, we consider all of its state non-essential and add it
  // after creation.
  inflateNonEssential(state, Map newMap, Reader r) {
    if (state is List) {
      inflateNonEssentialFromList(state, newMap, r);
    } else {
      inflateNonEssentialFromMap(state, newMap, r);
    }
  }

  void inflateNonEssentialFromList(List state, Map newMap, Reader r) {
    var key;
    for (var each in state) {
      if (key == null) {
        key = each;
      } else {
        newMap[r.inflateReference(key)] = r.inflateReference(each);
        key = null;
      }
    }
  }

  void inflateNonEssentialFromMap(Map state, Map newMap, Reader r) {
    state.forEach((key, value) {
      newMap[r.inflateReference(key)] = r.inflateReference(value);
    });
  }

  bool get hasVariableLengthEntries => true;
}

/**
 * This rule handles primitive types, defined as those that we can normally
 * represent directly in the output format. We hard-code that to mean
 * num, String, and bool.
 */
class PrimitiveRule extends SerializationRule {
  bool appliesTo(object, Writer w) => isPrimitive(object);
  extractState(object, Function f, Writer w) => object;
  flatten(object, Writer writer) {}
  inflateEssential(state, Reader r) => state;
  inflateNonEssential(object, _, Reader r) {}

  bool get storesStateAsPrimitives => true;

  /**
   * Indicate whether we should save pointers to this object as references
   * or store the object directly. For primitives this depends on the format,
   * so we delegate to the writer.
   */
  bool shouldUseReferenceFor(object, Writer w) =>
      w.shouldUseReferencesForPrimitives;

  bool get hasVariableLengthEntries => false;
}

/** Typedef for the object construction closure used in ClosureRule. */
typedef ConstructType(Map m);

/** Typedef for the state-getting closure used in ClosureToMapRule. */
typedef Map<String, dynamic> GetStateType(object);

/** Typedef for the state-setting closure used in ClosureToMapRule. */
typedef void NonEssentialStateType(object, Map m);

/**
 * This is a rule where the extraction and creation are hard-coded as
 * closures. The result is expected to be a map indexed by field name.
 */
class ClosureRule extends CustomRule {

  /** The runtimeType of objects that this rule applies to. Used in appliesTo.*/
  final Type type;

  /** The function for constructing new objects when reading. */
  ConstructType construct;

  /** The function for returning an object's state as a Map. */
  GetStateType getStateFunction;

  /** The function for setting an object's state from a Map. */
  NonEssentialStateType setNonEssentialState;

  /**
   * Create a ClosureToMapRule for the given [type] which gets an object's
   * state by calling [getState], creates a new object by calling [construct]
   * and sets the new object's state by calling [setNonEssentialState].
   */
  ClosureRule(this.type, this.getStateFunction, this.construct,
      this.setNonEssentialState);

  bool appliesTo(object, Writer w) => object.runtimeType == type;

  getState(object) => getStateFunction(object);

  create(state) => construct(state);

  void setState(object, state) {
    if (setNonEssentialState == null) return;
    setNonEssentialState(object, state);
  }
}

/**
 * This rule handles things we can't pass directly, but only by reference.
 * If objects are listed in the namedObjects in the writer or serialization,
 * it will save the name rather than saving the state.
 */
class NamedObjectRule extends SerializationRule {
  /**
   * Return true if this rule applies to the object. Checked by looking up
   * in the namedObjects collection.
   */
  bool appliesTo(object, Writer writer) {
    return writer.hasNameFor(object);
  }

  /** Extract the state of the named objects as just the object itself. */
  extractState(object, Function f, Writer writer) {
    var result = [nameFor(object, writer)];
    f(result.first);
    return result;
  }

  /** When we flatten the state we save it as the name. */
  // TODO(alanknight): This seems questionable. In a truly flat format we may
  // want to have extracted the name as a string first and flatten it into a
  // reference to that. But that requires adding the Writer as a parameter to
  // extractState, and I'm reluctant to add yet another parameter until
  // proven necessary.
  flatten(state, Writer writer) {
    state[0] = writer._referenceFor(state[0]);
  }

  /** Look up the named object and return it. */
  inflateEssential(state, Reader r) =>
      r.objectNamed(r.resolveReference(state.first));

  /** Set any non-essential state on the object. For this rule, a no-op. */
  inflateNonEssential(state, object, Reader r) {}

  /** Return the name for this object in the Writer. */
  String nameFor(object, Writer writer) => writer.nameFor(object);
}

/**
 * This rule handles the special case of Mirrors. It stores the mirror by its
 * qualifiedName and attempts to look it up in both the namedObjects
 * collection, or if it's not found there, by looking it up in the mirror
 * system. When reading, the user is responsible for supplying the appropriate
 * values in [Serialization.namedObjects] or in the [externals] paramter to
 * [Serialization.read].
 */
class MirrorRule extends NamedObjectRule {
  bool appliesTo(object, Writer writer) => object is DeclarationMirror;

  String nameFor(DeclarationMirror object, Writer writer) =>
      MirrorSystem.getName(object.qualifiedName);

  inflateEssential(state, Reader r) {
    var qualifiedName = r.resolveReference(state.first);
    var lookupFull = r.objectNamed(qualifiedName, (x) => null);
    if (lookupFull != null) return lookupFull;
    var separatorIndex = qualifiedName.lastIndexOf(".");
    var type = qualifiedName.substring(separatorIndex + 1);
    var lookup = r.objectNamed(type, (x) => null);
    if (lookup != null) return lookup;
    var name = qualifiedName.substring(0, separatorIndex);
    // This is very ugly. The library name for an unnamed library is its URI.
    // That can't be constructed as a Symbol, so we can't use findLibrary.
    // So follow one or the other path depending if it has a colon, which we
    // assume is in any URI and can't be in a Symbol.
    if (name.contains(":")) {
      var uri = Uri.parse(name);
      var libMirror = currentMirrorSystem().libraries[uri];
      return libMirror.classes[new Symbol(type)];
    } else {
      var symbol = new Symbol(name);
      var typeSymbol = new Symbol(type);
      var libMirror = currentMirrorSystem().findLibrary(symbol).firstWhere(
        (lib) => lib.classes[typeSymbol] != null);
      return libMirror.classes[typeSymbol];
    }
  }
}

/**
 * This provides an abstract superclass for writing your own rules specific to
 * a class. It makes some assumptions about behaviour, and so can have a
 * simpler set of methods that need to be implemented in order to subclass it.
 *
 */
abstract class CustomRule extends SerializationRule {
  // TODO(alanknight): It would be nice if we could provide an implementation
  // of appliesTo() here. If we add a type parameter to these classes
  // we can "is" test against it, but we need to be able to rule out subclasses.
  // => instance.runtimeType == T
  // should work.
  /**
   * Return true if this rule applies to this object, in the context
   * where we're writing it, false otherwise.
   */
  bool appliesTo(instance, Writer w);

  /**
   * Subclasses should implement this to return a list of the important fields
   * in the object. The order of the fields doesn't matter, except that the
   * create and setState methods need to know how to use it.
   */
  List getState(instance);

  /**
   * Given a [List] of the object's [state], re-create the object. This should
   * do the minimum needed to create the object, just calling the constructor.
   * Setting the remaining state of the object should be done in the [setState]
   * method, which will be called only once all the objects are created, so
   * it won't cause problems with cycles.
   */
  create(List state);

  /**
   * Set any state in [object] which wasn't set in the constructor. Between
   * this method and [create] all of the information in [state] should be set
   * in the new object.
   */
  void setState(object, List state);

  extractState(instance, Function f, Writer w) {
    var state = getState(instance);
    for (var each in values(state)) {
      f(each);
    }
    return state;
  }

  inflateEssential(state, Reader r) => create(_lazy(state, r));

  void inflateNonEssential(state, object, Reader r) {
    setState(object, _lazy(state, r));
  }

  // We don't want to have to make the end user tell us how long the list is
  // separately, so write it out for each object, even though they're all
  // expected to be the same length.
  bool get hasVariableLengthEntries => true;
}

/** A hard-coded rule for serializing Symbols. */
class SymbolRule extends CustomRule {
  bool appliesTo(instance, _) => instance is Symbol;
  getState(instance) => [MirrorSystem.getName(instance)];
  create(state) => new Symbol(state[0]);
  void setState(symbol, state) {}
  int get dataLength => 1;
  bool get hasVariableLengthEntries => false;
}

/** A hard-coded rule for DateTime. */
class DateTimeRule extends CustomRule {
  bool appliesTo(instance, _) => instance is DateTime;
  List getState(DateTime date) => [date.millisecondsSinceEpoch, date.isUtc];
  create(List state) =>
      new DateTime.fromMillisecondsSinceEpoch(state[0], isUtc: state[1]);
  void setState(date, state) {}
  // Let the system know we don't have to store a length for these.
  int get dataLength => 2;
  bool get hasVariableLengthEntries => false;
}

/** Create a lazy list/map that will inflate its items on demand in [r]. */
_lazy(l, Reader r) {
  if (l is List) return new _LazyList(l, r);
  if (l is Map) return new _LazyMap(l, r);
  throw new SerializationException("Invalid type: must be Map or List - $l");
}

/**
 * This provides an implementation of Map that wraps a list which may
 * contain references to (potentially) non-inflated objects. If these
 * are accessed it will inflate them. This allows us to pass something that
 * looks like it's just a list of objects to a [CustomRule] without needing
 * to inflate all the references in advance.
 */
class _LazyMap implements Map {
  _LazyMap(this._raw, this._reader);

  final Map _raw;
  final Reader _reader;

  // This is the only operation that really matters.
  operator [](x) => _reader.inflateReference(_raw[x]);

  int get length => _raw.length;
  bool get isEmpty => _raw.isEmpty;
  bool get isNotEmpty => _raw.isNotEmpty;
  Iterable get keys => _raw.keys;
  bool containsKey(x) => _raw.containsKey(x);

  // These operations will work, but may be expensive, and are probably
  // best avoided.
  get _inflated => keysAndValues(_raw).map(_reader.inflateReference);
  bool containsValue(x) => _inflated.containsValue(x);
  Iterable get values => _inflated.values;
  void forEach(f) => _inflated.forEach(f);

  // These operations are all invalid
  _throw() {
    throw new UnsupportedError("Not modifiable");
  }
  operator []=(x, y) => _throw();
  putIfAbsent(x, y) => _throw();
  remove(x) => _throw();
  clear() => _throw();
}

/**
 * This provides an implementation of List that wraps a list which may
 * contain references to (potentially) non-inflated objects. If these
 * are accessed it will inflate them. This allows us to pass something that
 * looks like it's just a list of objects to a [CustomRule] without needing
 * to inflate all the references in advance.
 */
class _LazyList extends IterableBase implements List {
  _LazyList(this._raw, this._reader);

  final List _raw;
  final Reader _reader;

  // This is the only operation that really matters.
  operator [](x) => _reader.inflateReference(_raw[x]);

  int get length => _raw.length;
  bool get isEmpty => _raw.isEmpty;
  get first => _reader.inflateReference(_raw.first);
  get last => _reader.inflateReference(_raw.last);

  // These operations, and other inherited methods that iterate over the whole
  // list will work, but may be expensive, and are probably
  // best avoided.
  Iterable get _inflated => _raw.map(_reader.inflateReference);
  Iterator get iterator => _inflated.iterator;
  indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
  lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
  sublist(start, [end]) => _inflated.sublist(start, end);

  Map<int, dynamic> asMap() => _inflated.asMap();

  // These operations are all invalid
  _throw() {
    throw new UnsupportedError("Not modifiable");
  }
  operator []=(x, y) => _throw();
  add(x) => _throw();
  addAll(x) => _throw();
  sort([f]) => _throw();
  clear() => _throw();
  insert(x, y) => _throw();
  insertAll(x, y) => _throw();
  fillRange(x, y, [z]) => _throw();
  removeAt(x) => _throw();
  remove(x) => _throw();
  removeLast() => _throw();
  removeAll(x) => _throw();
  retainAll(x) => _throw();
  removeWhere(x) => _throw();
  retainWhere(x) => _throw();
  replaceRange(x, y, z) => _throw();
  getRange(x, y) => _throw();
  setRange(x, y, z, [a = 0]) => _throw();
  setAll(x, y) => _throw();
  removeRange(x, y) => _throw();
  get reversed => _throw();
  void set length(x) => _throw();
}
