#= require angular/payrollhero_api/ph_restangular.coffee

describe 'angular:payrollhero.api.service(ScheduleEvent)', ->
  subject = undefined
  httpBackend = undefined
  instance = undefined
  params = undefined

  beforeEach ->
    module 'payrollhero.api'

  mtz = (string) ->
    moment.tz(string, 'America/Vancouver')

  beforeEach inject (ScheduleEvent, $httpBackend) ->
    subject = ScheduleEvent
    params = {
      "day_event_date": null,
      "day_event_name": null,
      "employee_id": 35,
      "id": 53465,
      "is_rest_day": false,
      "kind": "recurring_schedule",
      "recurrence_info": {
        "count": 1,
        "end_time": null,
        "exceptions": [
          "2015-01-19", # monday
          "2015-01-23", # sunday
        ],
        "on_friday": false,
        "on_monday": true,
        "on_saturday": false,
        "on_sunday": false,
        "on_thursday": true,
        "on_tuesday": false,
        "on_wednesday": true,
        "type": "week"
      },
      "shift_breaks": [
      ],
      "shift_end_time": "2014-11-05T03:00:00Z",
      "shift_start_time": "2014-11-04T19:00:00Z",
      "shift_time_zone": "America/Vancouver",
      "shift_worksite_id": 264
    }
    return

  make = ->
    instance = new subject()
    _.defaults(instance, params)

  describe 'a weekly recurring event', ->
    beforeEach make

    describe 'occursOn', ->
      it 'responds to all the interesting dates', ->
        expect(instance.occursOn(mtz('2015-01-11'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-12'))).toBeTruthy()
        expect(instance.occursOn(mtz('2015-01-13'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-14'))).toBeTruthy()
        expect(instance.occursOn(mtz('2015-01-15'))).toBeTruthy()
        expect(instance.occursOn(mtz('2015-01-16'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-17'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-18'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-19'))).toBeFalsy()

    describe 'overridesHoliday', ->
      it 'doesnt override', ->
        expect(instance.overridesHoliday()).toBeFalsy()

    it 'is a shift', ->
      expect(instance.isShift()).toBeTruthy()

    it 'is is a recurring schedule', ->
      expect(instance.isRecurringSchedule()).toBeTruthy()

    describe 'rangeOn', ->
      it 'gives back the range on that date or null if it does not occur', ->
        expect(instance.rangeOn(mtz('2015-01-11'))).toBeNull()
        range = instance.rangeOn(mtz('2015-01-12'))
        expect(range).not.toBeNull()
        expect(range.start).toEqualISO("2015-01-12T19:00:00.000Z")
        expect(range.end).toEqualISO("2015-01-13T03:00:00.000Z")

    describe 'recurringRangeOn', ->
      it 'gives me back the recurring range even if there are exceptions', ->
        expect(instance.recurringRangeOn(mtz('2015-01-11')).start).toEqualISO("2015-01-11T19:00:00.000Z")
        expect(instance.recurringRangeOn(mtz('2015-01-11')).end).toEqualISO("2015-01-12T03:00:00.000Z")

    describe 'isOverriddenOn', ->
      it 'answers for dates that have exceptions', ->
        expect(instance.isOverriddenOn(mtz('2015-01-19'))).toBeTruthy()
        expect(instance.isOverriddenOn(mtz('2015-01-12'))).toBeFalsy()

      # sometimes data is wrong.  it's technically not against this data format
      # for there to be an exception on a date where it doesn't recur
      # it doesn't make sense.  but we need to answer correctly
      it 'does not answer for dates it does not recur but has an exception', ->
        expect(instance.isOverriddenOn(mtz('2015-01-23'))).toBeFalsy()

  describe 'a weekly recurring event with count > 1', ->
    beforeEach ->
      params.recurrence_info.count = 2
      make()

    it 'throws an error for unsupported recurrence count', ->
      expect(( -> instance.occursOn(mtz('2015-01-11'))))
      .toThrow()

  describe 'a monthly recurring event', ->
    beforeEach ->
      params.recurrence_info = {
        count: 1,
        end_time: null,
        exceptions: [],
        type: 'month'
      }

    it 'repeats it on the same day each month', ->
      make()
      expect(instance.occursOn(mtz('2014-12-04'))).toBeTruthy()
      expect(instance.occursOn(mtz('2014-12-05'))).toBeFalsy()
      expect(instance.occursOn(mtz('2015-01-04'))).toBeTruthy()

    describe 'when it occurs with count=2', ->
      beforeEach ->
        params.recurrence_info.count = 2

      it 'repeats on the same day every other month', ->
        make()
        expect(instance.occursOn(mtz('2014-12-04'))).toBeFalsy()
        expect(instance.occursOn(mtz('2014-12-05'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-01-04'))).toBeTruthy()
        expect(instance.occursOn(mtz('2015-02-04'))).toBeFalsy()
        expect(instance.occursOn(mtz('2015-03-04'))).toBeTruthy()

  describe 'a holiday event', ->
    beforeEach ->
      params.recurrence_info = {type: 'none'}
      params.day_event_date = "2015-02-04"
      params.day_event_name = 'Happy Friends Day'
      params.kind = 'holiday'
      make()

    it 'is a whole day', ->
      expect(instance.isWholeDay()).toBeTruthy()
      expect(instance.isShift()).toBeFalsy()

    it 'occurs on the whole day', ->
      expect(instance.occursOn(moment('2015-02-03'))).toBeFalsy()
      expect(instance.occursOn(moment('2015-02-04'))).toBeTruthy()
      expect(instance.occursOn(moment('2015-02-05'))).toBeFalsy()

  describe 'a work this holiday event', ->
    beforeEach ->
      params.recurrence_info = {type: 'none'}
      params.employee_id = 1
      params.day_event_date = "2015-02-04"
      params.day_event_name = 'Nothing'
      params.kind = 'work_this_holiday'
      make()

    it 'is a whole day', ->
      expect(instance.isWholeDay()).toBeTruthy()
      expect(instance.isShift()).toBeFalsy()

    it 'overrides holidays', ->
      expect(instance.overridesHoliday()).toBeTruthy()

    it 'occurs on the whole day', ->
      expect(instance.occursOn(moment('2015-02-03'))).toBeFalsy()
      expect(instance.occursOn(moment('2015-02-04'))).toBeTruthy()
      expect(instance.occursOn(moment('2015-02-05'))).toBeFalsy()

  describe 'a weekly recurring event spanning a timezone change', ->
    beforeEach ->
      params.shift_start_time = "2014-10-30T19:00:00Z"
      params.shift_end_time = "2014-10-31T03:00:00Z"
      make()

    describe 'rangeOn', ->
      it 'gives back the range adjusted by DST', ->
        expect(instance.rangeOn(mtz('2015-01-11'))).toBeNull()
        range = instance.rangeOn(mtz('2015-01-12'))
        expect(range).not.toBeNull()
        expect(range.start).toEqualISO("2015-01-12T20:00:00.000Z")
        expect(range.end).toEqualISO("2015-01-13T04:00:00.000Z")

  describe 'a single event', ->
    beforeEach ->
      params.kind = 'single_shift'
      params.recurrence_info = {type: 'none'}
      make()

    it 'is a shift', ->
      expect(instance.isShift()).toBeTruthy()

    it 'is is not a recurring schedule', ->
      expect(instance.isRecurringSchedule()).toBeFalsy()

    describe 'occursOn', ->
      it 'only responds to the exact date defined in that timezone.', ->
        expect(instance.occursOn(mtz('2014-11-03'))).toBeFalsy()
        expect(instance.occursOn(mtz('2014-11-04'))).toBeTruthy()
        expect(instance.occursOn(mtz('2014-11-05'))).toBeFalsy()

    describe 'rangeOn', ->
      it 'returns null if it doesnt occur or the range of the single shift', ->
        expect(instance.rangeOn(mtz('2014-11-03'))).toBeNull()
        range = instance.rangeOn(mtz('2014-11-04'))
        expect(range).not.toBeNull()
        expect(range.start).toEqualISO("2014-11-04T19:00:00.000Z")
        expect(range.end).toEqualISO("2014-11-05T03:00:00.000Z")
