/**
 * @author Patrick Kopp
 */

function StrategyMutator(itsAnimator){

    var animator = itsAnimator;

    this.fadeStrategyToNewStrategy = function(strategy, newStrategy, steps){
        animator.addMutation(new MutationStrategyToStrategy(animator, strategy, newStrategy, steps));
    }

    this.fadeItemsToStrategy = function(items, newStrategy, steps){
        animator.addMutation(new MutationItemsToStrategy(animator, items, newStrategy, steps));
    }

    this.fadeItemToStrategy = function(item, strategy, steps){
        animator.addMutation(new MutationFadeItemToStrategy(animator, item, strategy, steps));
    }

    this.moveItemToPoint = function(item, point, steps) {
        animator.addMutation(new MutationItemToPoint(animator, item, point, steps));
    }

    this.lineUpItems = function(items, lineStart, lineEnd, steps){
        animator.addMutation(new MutationLineUpItems(animator, items, lineStart, lineEnd, steps));
    }

    this.lineUpItemsOfStrategy = function(strategyToTakeItemsFrom, lineStart, lineEnd, steps){
        animator.addMutation(new MutationLineUpItemsOfStrategy(animator, strategyToTakeItemsFrom, lineStart, lineEnd, steps));
    }

    this.fadeItemsToStandingTwisters = function(items, positions, fadeSteps, standSteps){
        animator.addMutation(new MutationItemsToStandingTwisters(animator, items, positions, fadeSteps, standSteps));
    }

    this.doWebJ = function(strategyToMutate, itemsToRemove, itemsToAdd){
        animator.addMutation(new MutationAddRemoveItems(animator, strategyToMutate, itemsToRemove, itemsToAdd));
    }
}

function MutationItemsToStandingTwisters(mAnimator, mItems, mPoints, mFadeSteps, mStandSteps){

        var animator = mAnimator;
        var items = mItems;
        var points = mPoints;
        var fadeSteps = mFadeSteps;
        var standSteps = mStandSteps;
        var frameOffset = Math.floor( standSteps / items.length - 1 );

        this.doIt = function(){
            for(var i = 0; i < items.length; i++){
                var strategy = new StrategyTwister(standSteps, points[i], standingRadius, standingAngSpeed);
                strategy.setFrame((i + 1) * frameOffset);
                animator.registerStrategyAutoUnregister(strategy);
                new MutationFadeItemToStrategy(animator, items[i], strategy, fadeSteps).doIt();
            }
        }
}

function MutationStrategyToStrategy(mAnimator, mStrategy, mNewStrategy, mSteps) {

    var animator = mAnimator;
    var strategy = mStrategy;
    var newStrategy = mNewStrategy;
    var steps = mSteps;

    this.doIt = function(){

        if(strategy == newStrategy) {return;}
        var items = strategy.getAllItems();
        new MutationItemsToStrategy(animator, items, newStrategy, steps).doIt();
    }
}

function MutationItemsToStrategy(mAnimator, mItems, mNewStrategy, mSteps){

    var animator = mAnimator;
    var items = mItems;
    var newStrategy = mNewStrategy;
    var steps = mSteps;

    this.doIt = function(){

        var futurePos = newStrategy.getFuturePoints(items.length, steps);
        for(var i = 0; i < items.length; i++){
            var item = items[i];
            if(item){
                var strategy = item.movementStrategy;
                var line = new StrategyLine(item, item.getPosition(), futurePos[i], steps);
    	        line.setNextStrategy(newStrategy);
    	        if(strategy != null){
    	            strategy.removeItem(item.id);
    	        }
                animator.registerStrategyAutoUnregister(line);
            }
        }
    }
}

function MutationItemToPoint(mAnimator, mItem, mPoint, mSteps){

    var animator = mAnimator;
    var item = mItem;
    var point = mPoint;
    var steps = mSteps;

    this.doIt = function(){
        var itemStrategy = item.movementStrategy;
        if(itemStrategy != null) {
            itemStrategy.setNextStrategy(null);
        }
      	var line = new StrategyLine(item, item.getPosition(), point, steps);
      	item.setMovementStrategy(line);
      	if(itemStrategy != null) {
      	    itemStrategy.removeItem(item.id);
      	}
      	animator.registerStrategyAutoUnregister(line);
    }
}

function MutationFadeItemToStrategy(mAnimator, mItem, mStrategy, mSteps){

    var animator = mAnimator;
    var item = mItem;
    var strategy = mStrategy;
    var steps = mSteps;

    this.doIt = function(){
        var itemStrategy = item.movementStrategy;
        if(itemStrategy == strategy) { return; }
        if(itemStrategy != null) { itemStrategy.removeItem(item.id); }

        var futurePos = strategy.getFuturePoints(1, steps);

        if(futurePos[0] == null){
            logDebug("item to strategy: " + strategy);
        }

        var line = new StrategyLine(item, item.getPosition(), futurePos[0], steps);
        itemStrategy = line;
        itemStrategy.setNextStrategy(strategy);
        animator.registerStrategyAutoUnregister(line);
    }
}

function MutationLineUpItems(mAnimator, mItems, mLineStart, mLineEnd, mSteps){
    var animator = mAnimator;
    var items = mItems;
    var lineStart = mLineStart;
    var lineEnd = mLineEnd;
    var steps = mSteps;

    this.doIt = function(){
      var line = new Line(lineStart, lineEnd);
    	var posToMoveTo = line.getPoints(items.length);

    	for(var i = 0; i < items.length; i++) {
    		new MutationItemToPoint(animator, items[i], posToMoveTo[i], steps).doIt();
    	}
    }
}

function MutationLineUpItemsOfStrategy(mAnimator, mStrategy, mLineStart, mLineEnd, mSteps){
    var animator = mAnimator;
    var strategy = mStrategy;
    var lineStart = mLineStart;
    var lineEnd = mLineEnd;
    var steps = mSteps;

    this.doIt = function(){
        new MutationLineUpItems(animator, mStrategy.getAllItems(), lineStart, lineEnd, steps);
    }
}

function MutationAddRemoveItems(meAnimator, meStrategyToMutate, mItemsToRemove, mItemsToAdd){

    var itemsToRemove = mItemsToRemove;
    var itemsToAdd = mItemsToAdd;
    var animator = meAnimator;
    var strategyToMutate = meStrategyToMutate;

    var transitionSteps = 50;

    this.doIt = function(){

        for(var i = 0; i < itemsToRemove.length; i++) {
            if(itemsToRemove[i] != null){
                var item = itemsToRemove[i];
                if(item.movementStrategy){
                    item.movementStrategy.removeItem(item);
                }
                item.hide();
                if(item.neighbor && $(item.neighbor.div)){
                    var elem = $(item.neighbor.div);
                    if(elem.parentNode){
                        elem.parentNode.removeChild(elem);
                    }
                }
                if($(item.div)){
                    var elem = $(item.div);
                    if(elem.parentNode){
                        elem.parentNode.removeChild(elem);
                    }
                }
                if(DEBUG) console.debug("webj: destroyed:" + item.id);

            }
        }

        for(var i = 0; i < itemsToAdd.length; i++) {

            var item = itemsToAdd[i];
            var mutator = new MutationFadeItemToStrategy(animator, item, strategyToMutate, transitionSteps);
            mutator.doIt();
            if(DEBUG) console.debug("webj: added:" + item.id);

//            var futurePos = strategyToMutate.getFuturePoints(1, transitionSteps);
//            var line = new StrategyLine(item, item.getPosition(), futurePos[0], transitionSteps);
//            line.setNextStrategy(strategyToMutate);
//	          animator.registerStrategyAutoUnregister(line);
//            if(DEBUG) console.debug("webj: added:" + item.id);
    	  }
    }
}

  function LetThemHop(animator, items, points, steps){
    var animator = animator;
    var steps = steps;
    var items = items;
    var computedPoints = [];

    items.each(function(item) {

      var pointsOfItem = [];
      var pos = item.getPosition();
      //pointsOfItem.push(new StrategyPause(item, 1000));
      points.each(function(point) {
        pointsOfItem.push(point.add(pos));
      });
      computedPoints.push(pointsOfItem);
    }.bind(this));

    this.doIt = function(){

        for(var i = 0; i < computedPoints.length; i++) {

          var item = items[i];
          var pointsOfItem = computedPoints[i];

          var poli = new StrategyPolygon(item, pointsOfItem, false, steps);
          animator.registerStrategyAutoUnregister(poli);
        }
     }
  }

  function LetThemHop2(animator, items, amplitude, hops, steps, delay){
    var animator = animator;
    var items = items;
    var amplitude = amplitude;
    var hops = hops;
    var steps = steps;
    var delay = delay;
    var computedPoints = [];

    items.each(function(item) {

      var pointsOfItem = [];
      //pointsOfItem.push(new StrategyPause(item, Math.round(Math.random() * delay)));

      var pos = item.getPosition();

      for(var i = 0; i < hops; i++) {
        var x = Math.round(Math.random() * amplitude);
        var y = Math.round(Math.random() * amplitude);
        pointsOfItem.push(pos.add(new Point(x, y)));
      }

      pointsOfItem.push(pos.clone());

      computedPoints.push(pointsOfItem);

    }.bind(this));

    //alert(computedPoints.join("\n"));

    this.doIt = function(){

        for(var i = 0; i < computedPoints.length; i++) {

          var item = items[i];
          var pointsOfItem = computedPoints[i];

          var poli = new StrategyPolygon(item, pointsOfItem, false, steps);
          animator.registerStrategyAutoUnregister(poli);
        }
     }
  }
