'use strict';

/**
 * @ngdoc directive
 * @name angular.module.ng.$compileProvider.directive.ngSwitch
 * @restrict EA
 *
 * @description
 * Conditionally change the DOM structure.
 *
 * @usageContent
 * <ANY ng-switch-when="matchValue1">...</ANY>
 *   <ANY ng-switch-when="matchValue2">...</ANY>
 *   ...
 *   <ANY ng-switch-default>...</ANY>
 *
 * @scope
 * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
 * @paramDescription
 * On child elments add:
 *
 * * `ngSwitchWhen`: the case statement to match against. If match then this
 *   case will be displayed.
 * * `ngSwitchDefault`: the default case when no other casses match.
 *
 * @example
    <doc:example>
      <doc:source>
        <script>
          function Ctrl($scope) {
            $scope.items = ['settings', 'home', 'other'];
            $scope.selection = $scope.items[0];
          }
        </script>
        <div ng-controller="Ctrl">
          <select ng-model="selection" ng-options="item for item in items">
          </select>
          <tt>selection={{selection}}</tt>
          <hr/>
          <div ng-switch on="selection" >
            <div ng-switch-when="settings">Settings Div</div>
            <span ng-switch-when="home">Home Span</span>
            <span ng-switch-default>default</span>
          </div>
        </div>
      </doc:source>
      <doc:scenario>
        it('should start in settings', function() {
         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);
        });
        it('should change to home', function() {
         select('selection').option('home');
         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);
        });
        it('should select deafault', function() {
         select('selection').option('other');
         expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);
        });
      </doc:scenario>
    </doc:example>
 */
var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
  restrict: 'EA',
  compile: function(element, attr) {
    var watchExpr = attr.ngSwitch || attr.on,
        cases = {};

    element.data(NG_SWITCH, cases);
    return function(scope, element){
      var selectedTransclude,
          selectedElement,
          selectedScope;

      scope.$watch(watchExpr, function(value) {
        if (selectedElement) {
          selectedScope.$destroy();
          selectedElement.remove();
          selectedElement = selectedScope = null;
        }
        if ((selectedTransclude = cases['!' + value] || cases['?'])) {
          scope.$eval(attr.change);
          selectedScope = scope.$new();
          selectedTransclude(selectedScope, function(caseElement) {
            selectedElement = caseElement;
            element.append(caseElement);
          });
        }
      });
    };
  }
});

var ngSwitchWhenDirective = ngDirective({
  transclude: 'element',
  priority: 500,
  compile: function(element, attrs, transclude) {
    var cases = element.inheritedData(NG_SWITCH);
    assertArg(cases);
    cases['!' + attrs.ngSwitchWhen] = transclude;
  }
});

var ngSwitchDefaultDirective = ngDirective({
  transclude: 'element',
  priority: 500,
  compile: function(element, attrs, transclude) {
    var cases = element.inheritedData(NG_SWITCH);
    assertArg(cases);
    cases['?'] = transclude;
  }
});
