var extend = require('extend-merge').extend;
var merge = require('extend-merge').merge;

class Transition {

  constructor(config) {
    config = extend({
      from: null,
      to: null,
      params: {}
    }, config);

    /**
     * From state.
     *
     * @var String
     */
    this._from = config['from'];

    /**
     * To state.
     *
     * @var String
     */
    this._to = config['to'];

    /**
     * Router instance.
     *
     * @var Array
     */
    this._params = config['params'];
  }

  /**
   * Gets sets the current route.
   *
   * @param  Object      params The route to set or none to get the setted one.
   * @return Object|self        The route on get or `this` on set.
   */
  from(from) {
    if (!arguments.length) {
      return this._from;
    }
    this._from = from;
    return this;
  }

  /**
   * Gets sets the new route.
   *
   * @param  Object      params The route to set or none to get the setted one.
   * @return Object|self        The route on get or `this` on set.
   */
  to(to) {
    if (!arguments.length) {
      return this._to;
    }
    this._to = to;
    return this;
  }

  /**
   * Gets the list of routes to unmount.
   *
   * @return Array The routes to unmount.
   */
  disabled(params) {
    var list = [];
    var from = this.from();

    if (!from) {
      return list;
    }

    var to = this.to();

    var origin = from.hierarchy();
    var len = origin.length;

    var target = to.hierarchy() || [];

    for (var index = 0; index < len; index++) {
      if (origin[index] !== target[index] || !target[index].matchParams(params, this.params())) {
        var i = len - 1;
        while (i >= index) {
          list.push(origin[i]);
          i--;
        }
        return list;
      }
    }
    return list;
  }

  /**
   * Gets the list of routes to mount.
   *
   * @return Array The routes to unmout.
   */
  enabled(params) {
    var list = [];
    var from = this.from();
    var to = this.to();

    var target = to.hierarchy();

    var index = 0;
    var len = target.length;

    if (from) {
      var origin = from.hierarchy();

      for (index = 0; index < len; index++) {
        if (origin[index] !== target[index] || !target[index].matchParams(params, this.params())) {
          break;
        }
      }
    }

    for (var i = index; i < len; i++) {
      list.push(target[i]);
    }

    return list;
  }

  /**
   * Gets sets the transition params.
   *
   * @param  Object      params The transition's params to set or none to get the setted one.
   * @return Object|self        The transition's params on get or `this` on set.
   */
  params(params) {
    if (!arguments.length) {
      return this._params;
    }
    this._params = params;
    return this;
  }

}

module.exports = Transition;

@@ -1521,32 +1521,41 @@
 ++) %7B%0A      if (
+%0A        
 origin%5Bindex%5D !=
@@ -1564,32 +1564,40 @@
 target%5Bindex%5D %7C%7C
+%0A       
  !target%5Bindex%5D.
@@ -1622,32 +1622,115 @@
 , this.params())
+ %7C%7C%0A        origin%5Bindex%5D.link(params) !== target%5Bindex%5D.link(this.params())%0A      
 ) %7B%0A        var 
@@ -2269,16 +2269,27 @@
     if (
+%0A          
 origin%5Bi
@@ -2314,16 +2314,26 @@
 ndex%5D %7C%7C
+%0A         
  !target
@@ -2374,16 +2374,103 @@
 arams())
+ %7C%7C%0A          origin%5Bindex%5D.link(params) !== target%5Bindex%5D.link(this.params())%0A        
 ) %7B%0A    

Assume states are differents when paths are differents.