(function(ionic) {
'use strict';

/**
 * The NavController makes it easy to have a stack
 * of views or screens that can be pushed and popped
 * for a dynamic navigation flow. This API is modelled
 * off of the UINavigationController in iOS.
 *
 * The NavController can drive a nav bar to show a back button
 * if the stack can be poppped to go back to the last view, and
 * it will handle updating the title of the nav bar and processing animations.
 */
ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
  initialize: function(opts) {
    var _this = this;

    this.navBar = opts.navBar;
    this.content = opts.content;
    this.controllers = opts.controllers || [];

    this._updateNavBar();

    // TODO: Is this the best way?
    this.navBar.shouldGoBack = function() {
      _this.pop();
    };
  },

  /**
   * @return {array} the array of controllers on the stack.
   */
  getControllers: function() {
    return this.controllers;
  },

  /**
   * @return {object} the controller at the top of the stack.
   */
  getTopController: function() {
    return this.controllers[this.controllers.length-1];
  },

  /**
   * Push a new controller onto the navigation stack. The new controller
   * will automatically become the new visible view.
   *
   * @param {object} controller the controller to push on the stack.
   */
  push: function(controller) {
    var last = this.controllers[this.controllers.length - 1];

    this.controllers.push(controller);

    // Indicate we are switching controllers
    var shouldSwitch = this.switchingController && this.switchingController(controller) || true;

    // Return if navigation cancelled
    if(shouldSwitch === false)
      return;

    // Actually switch the active controllers
    if(last) {
      last.isVisible = false;
      last.visibilityChanged && last.visibilityChanged('push');
    }

    // Grab the top controller on the stack
    var next = this.controllers[this.controllers.length - 1];

    next.isVisible = true;
    // Trigger visibility change, but send 'first' if this is the first page
    next.visibilityChanged && next.visibilityChanged(last ? 'push' : 'first');

    this._updateNavBar();

    return controller;
  },

  /**
   * Pop the top controller off the stack, and show the last one. This is the
   * "back" operation.
   *
   * @return {object} the last popped controller
   */
  pop: function() {
    var next, last;

    // Make sure we keep one on the stack at all times
    if(this.controllers.length < 2) {
      return;
    }

    // Grab the controller behind the top one on the stack
    last = this.controllers.pop();
    if(last) {
      last.isVisible = false;
      last.visibilityChanged && last.visibilityChanged('pop');
    }
    
    // Remove the old one
    //last && last.detach();

    next = this.controllers[this.controllers.length - 1];

    // TODO: No DOM stuff here
    //this.content.el.appendChild(next.el);
    next.isVisible = true;
    next.visibilityChanged && next.visibilityChanged('pop');

    // Switch to it (TODO: Animate or such things here)

    this._updateNavBar();

    return last;
  },

  /**
   * Show the NavBar (if any)
   */
  showNavBar: function() {
    if(this.navBar) {
      this.navBar.show();
    }
  },

  /**
   * Hide the NavBar (if any)
   */
  hideNavBar: function() {
    if(this.navBar) {
      this.navBar.hide();
    }
  },

  // Update the nav bar after a push or pop
  _updateNavBar: function() {
    if(!this.getTopController() || !this.navBar) {
      return;
    }

    this.navBar.setTitle(this.getTopController().title);

    if(this.controllers.length > 1) {
      this.navBar.showBackButton(true);
    } else {
      this.navBar.showBackButton(false);
    }
  }
});

})(window.ionic);
