'use strict';

/**
 * @ngdoc directive
 * @name ng.directive:ngController
 *
 * @description
 * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
 * supports the principles behind the Model-View-Controller design pattern.
 *
 * MVC components in angular:
 *
 * * Model — The Model is scope properties; scopes are attached to the DOM where scope properties
 *   are accessed through bindings.
 * * View — The template (HTML with data bindings) that is rendered into the View.
 * * Controller — The `ngController` directive specifies a Controller class; the class contains business
 *   logic behind the application to decorate the scope with functions and values
 *
 * Note that you can also attach controllers to the DOM by declaring it in a route definition
 * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
 * again using `ng-controller` in the template itself.  This will cause the controller to be attached
 * and executed twice.
 *
 * @element ANY
 * @scope
 * @param {expression} ngController Name of a globally accessible constructor function or an
 *     {@link guide/expression expression} that on the current scope evaluates to a
 *     constructor function. The controller instance can be published into a scope property
 *     by specifying `as propertyName`.
 *
 * @example
 * Here is a simple form for editing user contact information. Adding, removing, clearing, and
 * greeting are methods declared on the controller (see source tab). These methods can
 * easily be called from the angular markup. Notice that the scope becomes the `this` for the
 * controller's instance. This allows for easy access to the view data from the controller. Also
 * notice that any changes to the data are automatically reflected in the View without the need
 * for a manual update. The example is shown in two different declaration styles you may use
 * according to preference.
   <doc:example>
     <doc:source>
      <script>
        function SettingsController1() {
          this.name = "John Smith";
          this.contacts = [
            {type: 'phone', value: '408 555 1212'},
            {type: 'email', value: 'john.smith@example.org'} ];
          };

        SettingsController1.prototype.greet = function() {
          alert(this.name);
        };

        SettingsController1.prototype.addContact = function() {
          this.contacts.push({type: 'email', value: 'yourname@example.org'});
        };

        SettingsController1.prototype.removeContact = function(contactToRemove) {
         var index = this.contacts.indexOf(contactToRemove);
          this.contacts.splice(index, 1);
        };

        SettingsController1.prototype.clearContact = function(contact) {
          contact.type = 'phone';
          contact.value = '';
        };
      </script>
      <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
        Name: <input type="text" ng-model="settings.name"/>
        [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
        Contact:
        <ul>
          <li ng-repeat="contact in settings.contacts">
            <select ng-model="contact.type">
               <option>phone</option>
               <option>email</option>
            </select>
            <input type="text" ng-model="contact.value"/>
            [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
            | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
          </li>
          <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
       </ul>
      </div>
     </doc:source>
     <doc:protractor>
       it('should check controller as', function() {
         var container = element(by.id('ctrl-as-exmpl'));

         expect(container.findElement(by.model('settings.name'))
             .getAttribute('value')).toBe('John Smith');

         var firstRepeat =
             container.findElement(by.repeater('contact in settings.contacts').row(0));
         var secondRepeat =
             container.findElement(by.repeater('contact in settings.contacts').row(1));

         expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('408 555 1212');
         expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('john.smith@example.org');

         firstRepeat.findElement(by.linkText('clear')).click()

         expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('');

         container.findElement(by.linkText('add')).click();

         expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
             .findElement(by.model('contact.value'))
             .getAttribute('value'))
             .toBe('yourname@example.org');
       });
     </doc:protractor>
   </doc:example>
    <doc:example>
     <doc:source>
      <script>
        function SettingsController2($scope) {
          $scope.name = "John Smith";
          $scope.contacts = [
            {type:'phone', value:'408 555 1212'},
            {type:'email', value:'john.smith@example.org'} ];

          $scope.greet = function() {
           alert(this.name);
          };

          $scope.addContact = function() {
           this.contacts.push({type:'email', value:'yourname@example.org'});
          };

          $scope.removeContact = function(contactToRemove) {
           var index = this.contacts.indexOf(contactToRemove);
           this.contacts.splice(index, 1);
          };

          $scope.clearContact = function(contact) {
           contact.type = 'phone';
           contact.value = '';
          };
        }
      </script>
      <div id="ctrl-exmpl" ng-controller="SettingsController2">
        Name: <input type="text" ng-model="name"/>
        [ <a href="" ng-click="greet()">greet</a> ]<br/>
        Contact:
        <ul>
          <li ng-repeat="contact in contacts">
            <select ng-model="contact.type">
               <option>phone</option>
               <option>email</option>
            </select>
            <input type="text" ng-model="contact.value"/>
            [ <a href="" ng-click="clearContact(contact)">clear</a>
            | <a href="" ng-click="removeContact(contact)">X</a> ]
          </li>
          <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
       </ul>
      </div>
     </doc:source>
     <doc:protractor>
       it('should check controller', function() {
         var container = element(by.id('ctrl-exmpl'));

         expect(container.findElement(by.model('name'))
             .getAttribute('value')).toBe('John Smith');

         var firstRepeat =
             container.findElement(by.repeater('contact in contacts').row(0));
         var secondRepeat =
             container.findElement(by.repeater('contact in contacts').row(1));

         expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('408 555 1212');
         expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('john.smith@example.org');

         firstRepeat.findElement(by.linkText('clear')).click()

         expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
             .toBe('');

         container.findElement(by.linkText('add')).click();

         expect(container.findElement(by.repeater('contact in contacts').row(2))
             .findElement(by.model('contact.value'))
             .getAttribute('value'))
             .toBe('yourname@example.org');
       });
     </doc:protractor>
   </doc:example>

 */
var ngControllerDirective = [function() {
  return {
    scope: true,
    controller: '@',
    priority: 500
  };
}];
