<!DOCTYPE html>
<html ng-app="app">

  <head>
    <link data-require="jasmine@1.3.1" data-semver="1.3.1" rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" />
    <link rel="stylesheet" href="style.css">
    
    <script data-require="moment.js@*" data-semver="2.8.3" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
    <script data-require="underscore.js@*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
    <script data-require="angular-messages@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular-messages.js"></script>
    
    <script data-require="jasmine@1.3.1" data-semver="1.3.1" src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
    <script data-require="jasmine@1.3.1" data-semver="1.3.1" src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.0-rc.2/angular.js" data-semver="1.4.0-rc.2"></script>
    <script data-require="angular-mocks@*" data-semver="1.4.0-rc.2" src="https://code.angularjs.org/1.4.0-rc.2/angular-mocks.js"></script>
    <script src="app.js"></script>
<!--     <script src="appSpec.js"></script>
<script src="jasmineBootstrap.js"></script> -->
  </head>

  <body ng-controller="MainController as main">
    <form name='dateForm' ng-submit='main.submit()'>
      <date-range-form-directive ng-model="main.date"></date-range-form-directive>
      <input type='submit' />
    </form>
    <div ng-include="main.templateUrl"></div>
  </body>

</html>
// Code goes here

var app = angular.module('app', []);

app.controller('MainController', MainController);
app.directive('monthYearPickerDirective', monthYearPickerDirective);
app.directive('dateRangeFormDirective', dateRangeFormDirective);
app.directive('monthDirective', monthDirective);


function MainController($scope) {
  var vm = this;

  vm.date = {};
  vm.date.from = {month: null, year: null}; 
  vm.date.to   = {month: null, year: null, ongoing: false}; 
  
  $scope.test = 'string:1';
  
  vm.submit = function() {
    vm.templateUrl = 'happy-booking-template.html';
  }
  
}

function dateRangeFormDirective() {
  var directive = {
    restrict: 'E',
    templateUrl: 'date-range-form-template.html',
    require: 'ngModel',
    transclude: true,
    link: link
  };
  return directive;
  
  function link(scope, elem, attrs, ctrl) {
    scope.formCtrl = ctrl; //Errors will be on the form - NOT on individual fields
    
    scope.isValid = function() {
      if(gotToAndFromDates()) {
        becomeDates();
       if(datesAreValid()) ctrl.$validate(); 
      }
    }
    
    ctrl.$validators.startDateAfterEndDate = function() {
      return (scope.ngModel &&
      scope.ngModel.date.from.moment &&
      scope.ngModel.date.to.moment &&
      scope.ngModel.date.from.moment.isBefore(scope.ngModel.date.to.moment) ) 
    }
    
    function toDate(stage) {
      var e = scope.ngModel.date[stage];
      return new Date(e.year, e.month)
    }
    
    function becomeDates() {
      scope.ngModel.date.to.moment = moment(new Date(scope.ngModel.date.to.year + '-' + scope.ngModel.date.to.month)).endOf('month');
      if(scope.main.date) {
        scope.main.date.from.moment = scope.ngModel.date.from.moment;
        scope.main.date.to.moment = scope.ngModel.date.to.moment;
      }
      
    }

    function datesAreValid() {
      return scope.ngModel.date.from.moment.isValid() && scope.ngModel.date.to.moment.isValid(); 
    }
    
    function gotToAndFromDates() {
      return scope.ngModel && scope.ngModel.date.from && scope.ngModel.date.to;
    }
  }
}


function monthYearPickerDirective() {
  var directive = {
    restrict: 'E',
    templateUrl: 'month-year-template.html',
    //template: '<select name="{{label}}month" ng-model="ngModel.month" ng-options="c as c for c in months" required></select><select name="{{label}}year" ng-model="ngModel.year" ng-options="c as c for c in years" required ></select>',
    require: 'ngModel',
    scope: {
      label: '@', //label for us to differntiate if 'FROM' or 'TO' date
      ngModel: '=', //Object {month: null, year: null}
      onSelected: '&' //is the function we will call on the parent directive
    },
    transclude: true,
    link: link
  };
  return directive;
  
  function link(scope, elem, attrs, ctrl) {
    scope.label = attrs.label;
    scope.months = returnMonths();
    scope.years = returnYears();
    scope.fromLabel = scope.label === 'from' ? true : false; 
    
    scope.$watch('ngModel.month', newValueTrigger);
    scope.$watch('ngModel.year', newValueTrigger);

    function newValueTrigger() {
      if(isFormEvenValid()) {
        scope.onSelected();
      }
    }
    
    function isFormEvenValid() {
      return (scope.ngModel && scope.ngModel.month && scope.ngModel.year);
    }
    
    /* Helper Functions */
    
    function returnMonths() {
      var array = [];
      for (var i = 1; i < 12; i++) {
        //var monthName = moment('2014 ' + i + ' 25').format('MMMM'); //TODO Add locale('fr') - tie it to ng-translate
        var selectOptionValue =  moment('2014 ' + i + ' 25').format('M');
        array.push(selectOptionValue);
      }
      return array;
    }

    function returnYears() {
      var array = [];
      for (var i = 1950; i < 2050; i++) {
        var date = moment(i + ' 1 25').format('YYYY'); //TODO Add locale('fr') - tie it to ng-translate
        array.push(date);
      }
      return array;
    }
  }
}
/* Styles go here */

.box {
  width: 100%;
  height: 200px;
  background: red;
  border: 5px solid green;
  color: white;
}
<div>
<label>{{label | uppercase}}</label>
<div>
<select 
  name="{{label}}month"
  ng-model="ngModel.month" 
  ng-options="c as c for c in months" 
  month-directive
  required
  ></select>
  
  <select 
  name="{{label}}year"
  ng-model="ngModel.year" 
  ng-options="c as c for c in years" 
  required
  ></select>

{{$parent.formCtrl}}
  <div ng-messages="$parent.formCtrl.$error" ng-if="fromLabel && $parent.formCtrl.$invalid">
        <div ng-message="startDateAfterEndDate">Start Date is before endDate</div>
  </div>

</div>

</div>
<ng-form name='childForm'>
  <month-year-picker-directive label='from' on-selected='isValid()' ng-model='ngModel.date.from'></month-year-picker-directive>
  <month-year-picker-directive label='to' on-selected='isValid()' ng-model='ngModel.date.to'></month-year-picker-directive>
  <input type="checkbox" /> 
</ng-form>
<div class='box'>
  <h1>Hurray - we booked your flight</h1>
  Your vacation starts on: {{main.date.from.moment}}
  <br />
  Your vacation ends on: {{main.date.to.moment}}
  <br />
  No worries - I am sure you will go again next year :)
</div>
describe('App Test', function() {
  var $scope = null;
  var $rootScope = null; 
  var ctrl = null;
  var compileFn = null;
  var $httpBackend = null;
  
  //you need to indicate your module in a test
  beforeEach(module('app'));

  beforeEach(inject(function(_$rootScope_, $controller, $compile, _$httpBackend_) {
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();
    $httpBackend = _$httpBackend_;
    
    ctrl = $controller('MainController', {
      $scope: $scope
    });
    
    
    // compileFn = $compile(
    //   '<ng-form name="child-form"><month-year-picker-directive label="from" on-selected="isValid()" ng-model="ngModel.date.from"></month-year-picker-directive>' +
    //   '<month-year-picker-directive label="from" on-selected="isValid()" ng-model="ngModel.date.from"></month-year-picker-directive></ng-form>'
    // );
    
    compileFn = $compile(
      '<month-year-picker-directive label="from" on-selected="isValid()" ng-model="date.from"></month-year-picker-directive>'
    );
    
  }));
  
  describe('MainController', function() {
    it('should have date object inside controller', function() {
    expect(ctrl.date.from.month).toBe(null);
  });    
  });
  
  
  describe('dateRangeForm Directive', function() {
    var to, from, fillDirective;
    
    beforeEach(function() {
      to = {
        month: 'string:03',
        year: 'string:2013'
      };
      from = {
        month: 'string:01',
        year: 'string:2013'
      };
      
      fillDirective = function() {
        var e = compileFn($scope);
        $rootScope.$digest();
        return e;
      }
      ctrl.date.from = from;
      ctrl.date.to = to;
    });
    
    it('should pass validation on an element', function(){
      fillDirective();
      ctrl.date.from.month = 'string:07';
      fillDirective();
      expect(ctrl.date.from.month).toBe('string:07');
    });
    
    it('should re-map dates correctly - if available on the Controller', function() {
      //Here if we stored some date on the server - and they are in EDIT mode
      // ctrl.date.from = '2015-03-01';
      // ctrl.date.from.month = 'string:3';
      // var element = compileFn($scope);
      // $rootScope.$digest();
      // console.log('element', element);
      // console.log('select', element[0].children[0]);
      // expect(ctrl.date.from.month).toBe('2015-03-01');
    });
    
    it('should produce a valid date from moment format MMM for cross browser', function() {
      // $scope.from = '2015-March-01'; //Invalid in IE/FF
      // var element = compileFn($scope);
      // $rootScope.$digest();
      // expect(ctrl.date.from.date.isValid()).toBe(true);
    });
    
    it('should produce a valid UTC date if non UTC date given', function() {
      //UTC inconsistencies - ('2015-03-01') - really -- ('2015-02-28')
    });
    
    
    it('should produce an end of month date in UTC', function() {
      //new Date ('2015-03').endOf('month') - will not work 
        var date = moment(new Date(Date.UTC(2015, 12, 0, 0, 0, 0)));
        //var computedDate = moment(new Date("2015-12-31")).utcOffset(-240);
        expect(date.isSame(date)).toBe(true);
    });
    
  
  });

  
  // it('should return a valid map URL if markers are NOT available', function() {
  //   var url = myService.getMapUrl(undefined, {size: 'small'});
  //   expect(url).not.toContain('pin_family.png');
  // });
  
  // it('should not process and an undefined marker', function() {
  //   var markers = [{"latitude":undefined,"longitude":undefined, icon: 'undefined'}];
  //   var url = myService.getMapUrl(markers, {size: 'small'});
  //   expect(url).not.toContain('undefined');
  //   expect(url).toContain('png');
  //   expect(urlRegEx.test(url)).toBe(true);
  // });
});
(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 250;

  /**
   Create the `HTMLReporter`, which Jasmine calls to provide results of each spec and each suite. The Reporter is responsible for presenting results to the user.
   */
  var htmlReporter = new jasmine.HtmlReporter();
  jasmineEnv.addReporter(htmlReporter);

  /**
   Delegate filtering of specs to the reporter. Allows for clicking on single suites or specs in the results to only run a subset of the suite.
   */
  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  /**
   Run all of the tests when the page finishes loading - and make sure to run any previous `onload` handler

   ### Test Results

   Scroll down to see the results of all of these specs.
   */
  var currentWindowOnload = window.onload;
  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }

    //document.querySelector('.version').innerHTML = jasmineEnv.versionString();
    execJasmine();
  };

  function execJasmine() {
    jasmineEnv.execute();
  }
})();