/*globals Ember */
// import Ember from "ember-metal/core"; // Ember.assert, Ember.K
var merge = Ember.merge; // import merge from "ember-metal/merge";
var get = Ember.get; // import { get } from "ember-metal/property_get";
var set = Ember.set; // import { set } from "ember-metal/property_set";
var View = Ember.View; // import View from "ember-views/views/view";
var EmberError = Ember.Error; // import EmberError from "ember-metal/error";
var run = Ember.run; // import run from "ember-metal/run_loop";
// import {
//   cloneStates,
//   states as EmberViewStates
// } from "ember-views/views/states";
var StatesModule = Ember.__loader.require('ember-views/views/states');
var cloneStates = StatesModule.cloneStates;
var EmberViewStates = StatesModule.states;

/**
@module ember
@submodule ember-views
*/

var EmberRenderer = Ember.__loader.require('ember-views/system/renderer')['default'];
EmberRenderer.prototype.childViews = function(view) {
  if (view._firstChild) {
    // TODO: enable the renderer to loop over our linked list instead of generating an array AOT
    var views = [];
    var current = view._firstChild;
    while (current) {
      views.push(current);
      current = current._nextSibling;
    }
    return views;
  } else {
    return view._childViews;
  }
};


var states = cloneStates(EmberViewStates);

var CoreContainerView = View.extend({
  _states: states,

  _firstChild: null,
  _lastChild: null,

  pushObject: function(childView) {
    this.insertBefore(childView, null);
  },

  insertBefore: function(newChild, before) {
    if (!this._firstChild || this._firstChild === before) { this._firstChild = newChild; }

    // remove ourself from our previous and next siblings, this logic could probably be improved
    if (newChild._previousSibling) {
      newChild._previousSibling._nextSibling = newChild._nextSibling;

      if (!newChild._nextSibling) { this._lastChild = newChild._previousSibling; }
    }
    if (newChild._nextSibling) {
      newChild._nextSibling._previousSibling = newChild._previousSibling;
    }

    // relocate the view
    if (before) {
      newChild._previousSibling = before._previousSibling;
      newChild._nextSibling = before;
      if (before._previousSibling) { before._previousSibling._nextSibling = newChild; }
      before._previousSibling = newChild;
    } else if (this._lastChild !== newChild) {
      newChild._previousSibling = this._lastChild;
      if (this._lastChild) {
        this._lastChild._nextSibling = newChild;
      }
      this._lastChild = newChild;
    }

    set(newChild, '_parentView', this); // only needed if we don't use createChildView
    newChild.container = this.container;
    if (!get(newChild, 'templateData')) {
      set(newChild, 'templateData', get(this, 'templateData'));
    }

    // TODO: megahax until morph has insertBefore API
    // this moves the view's morph into the correct location in the container's _childViewsMorph object
    if (newChild._elementCreated) {
      debugger;
      var morph = this._childViewsMorph;
      var fromIndex = morph.morphs.indexOf(newChild._morph);
      var toIndex;
      if (before) {
        toIndex = morph.morphs.indexOf(before._morph);
      } else {
        toIndex = morph.morphs.length - 1;
      }
      if (fromIndex !== toIndex) {
        morph.move(fromIndex, toIndex);
      }
    }

    run.scheduleOnce('render', this, '_ensureChildrenAreInDOM');
  },

  /**
    Instructs each child view to render to the passed render buffer.

    @private
    @method render
    @param {Ember.RenderBuffer} buffer the buffer to render to
  */
  render: function(buffer) {
    var element = buffer.element();
    var dom = buffer.dom;

    if (this.tagName === '') {
      if (this._morph) {
        this._childViewsMorph = this._morph;
      } else {
        element = dom.createDocumentFragment();
        this._childViewsMorph = dom.appendMorph(element);
      }
    } else {
      this._childViewsMorph = dom.createMorph(element, element.lastChild, null);
    }

    return element;
  },

  instrumentName: 'core_container',

  removeChild: function(child) {
    if (child._previousSibling) { child._previousSibling._nextSibling = child._nextSibling; }
    if (child._nextSibling) { child._nextSibling._previousSibling = child._previousSibling; }
    if (this._firstChild === child) { this._firstChild = child._nextSibling; }
    if (this._lastChild === child) { this._lastChild = child._previousSibling; }
    child.remove();
    // set(child, '_parentView', null); // FML, this will trigger a rerender :'(
    return this;
  },

  _ensureChildrenAreInDOM: function () {
    this.currentState.ensureChildrenAreInDOM(this);
  }
});

merge(states._default, {
  childViewsWillChange: Ember.K,
  childViewsDidChange: Ember.K,
  ensureChildrenAreInDOM: Ember.K
});

merge(states.inBuffer, {
  childViewsDidChange: function(parentView, views, start, added) {
    throw new EmberError('You cannot modify child views while in the inBuffer state');
  }
});

merge(states.hasElement, {
  ensureChildrenAreInDOM: function(view) {
    var current = view._firstChild;
    var renderer = view._renderer;
    var i = 0;

    while (current) {
      if (!current._elementCreated) {
        renderer.renderTree(current, view, i);
      }
      current = current._nextSibling;
      i++;
    }
  }
});

export default CoreContainerView;

@@ -3724,95 +3724,8 @@
 ) %7B%0A
-      if (this._morph) %7B%0A        this._childViewsMorph = this._morph;%0A      %7D else %7B%0A  
     
@@ -3764,24 +3764,55 @@
 agment();%0A  
+    buffer._element = element;%0A
       this._
@@ -3852,26 +3852,49 @@
 (element
-);%0A      %7D
+, this._morph.contextualElement);
 %0A    %7D e
@@ -3933,22 +3933,22 @@
 h = dom.
-create
+append
 Morph(el
@@ -3956,33 +3956,8 @@
 ment
-, element.lastChild, null
 );%0A 

Update CoreContainerView.render to support inclusive morph