#= require angular/payrollhero_api/ph_restangular.coffee

describe 'angular:payrollhero.api.service(ScheduleEventsService)', ->
  subject = undefined
  httpBackend = undefined
  EmployeeScheduleDayList = undefined
  scheduleEvents = []
  day = undefined
  daySchedules = undefined
  employee = null

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

  doNotExpectFailure = (error) ->
    console.error(error)
    throw "promise threw unexpected failure!"

  setupBasicScheduleEventsResponse = ->
    httpBackend.expectGET('http://api.payrollhero.dev/api/v4/schedule_events?page=1&token=t0ken')
    .respond(getJSONFixture('api/v4/schedules_response.json'))

  setupSingleEventResponse = ->
    httpBackend.expectGET('http://api.payrollhero.dev/api/v4/schedule_events?page=1&token=t0ken')
    .respond(getJSONFixture('api/v4/schedules_response_one_exception.json'))

  setupRecurringEventResponse = ->
    httpBackend.expectGET('http://api.payrollhero.dev/api/v4/schedule_events?page=1&token=t0ken')
    .respond(getJSONFixture('api/v4/schedules_response_one_recurring.json'))

  setupBasicEmployeeResponse = ->
    httpBackend.expectGET('http://api.payrollhero.dev/api/v3/employees?token=t0ken')
    .respond(getJSONFixture("api/v3/employees_response.json"))

  beforeEach ->
    module 'payrollhero.api'
    angular.module('payrollhero.api').constant('PhToken', {token: 't0ken'})

  beforeEach inject (ScheduleEventsService, $httpBackend, _EmployeeScheduleDayList_, _EmployeesService_) ->
    subject = ScheduleEventsService
    httpBackend = $httpBackend
    EmployeeScheduleDayList = _EmployeeScheduleDayList_
    EmployeesService = _EmployeesService_
    setupBasicEmployeeResponse()
    EmployeesService.getList().then (employees) ->
      employee = employees[0]
    $httpBackend.flush()
    return

  afterEach ->
    httpBackend.verifyNoOutstandingExpectation()
    httpBackend.verifyNoOutstandingRequest()

  day = mtz('2015-02-03')
  expectedExceptionJson = {"date": "2015-02-03"}

  describe '#getList', ->
    beforeEach ->
      setupBasicScheduleEventsResponse()
      return

    it 'queries the server and gives me the list with pagination info', ->
      subject.getList(page: 1).then (employeesList) ->
        expect(employeesList.page).toEqual(1)
        expect(employeesList.hasMorePages()).toBeFalsy()
        expect(employeesList.length).toEqual(105)
      .catch(doNotExpectFailure)
      httpBackend.flush()

  setupScheduleEvents = ->
    subject.getList(page: 1).then (items) ->
      expect(items.length).toEqual(1)
      scheduleEvents = items
    httpBackend.flush()

  describe '#createUnpaidDayOff', ->
    expectedData = {
      "schedule_event": {
        employee_id: 46
        "kind": "unpaid_day_off"
        "is_rest_day": false
        "day_event_date": "2015-02-03"
        "recurrence_info": {"type": "none"}
      }
    }

    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule Events', ->
      it 'posts ONE schedule', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createUnpaidDayOff(daySchedules)
        httpBackend.flush()

    describe 'when there is a non-recurring schedule', ->
      beforeEach ->
        setupSingleEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'deletes the schedule event and then posts one schedule', ->
        httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/51699?token=t0ken').respond(200)
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createUnpaidDayOff(daySchedules)
        httpBackend.flush()

    describe 'when there is a recurring schedule', ->
      beforeEach ->
        setupRecurringEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'deletes the schedule event and then posts one schedule', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events/51699/exceptions?token=t0ken',
          expectedExceptionJson)
        .respond({exceptions: ['2015-02-03']})
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createUnpaidDayOff(daySchedules)
        httpBackend.flush()

  describe '#createPaidDayOff', ->
    expectedData = {
      "schedule_event": {
        employee_id: 46
        "kind": "paid_day_off"
        "is_rest_day": false
        "day_event_date": "2015-02-03"
        "recurrence_info": {"type": "none"}
      }
    }

    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule Events', ->
      it 'posts ONE schedule', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createPaidDayOff(daySchedules)
        httpBackend.flush()

    describe 'when there is a non-recurring schedule', ->
      beforeEach ->
        setupSingleEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'deletes the schedule event and then posts one schedule', ->
        httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/51699?token=t0ken').respond(200)
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createPaidDayOff(daySchedules)
        httpBackend.flush()

    describe 'when there is a recurring schedule', ->
      beforeEach ->
        setupRecurringEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'deletes the schedule event and then posts one schedule', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events/51699/exceptions?token=t0ken',
          expectedExceptionJson)
        .respond({exceptions: ['2015-02-03']})
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createPaidDayOff(daySchedules)
        httpBackend.flush()

  describe '#createWorkThisHoliday', ->
    expectedData = {
      "schedule_event": {
        "day_event_date": "2015-02-03",
        "employee_id": 46,
        "is_rest_day": false,
        "kind": "work_this_holiday",
        "recurrence_info": {
          "type": "none"
        }
      }
    }

    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule Events', ->
      it 'posts one work this holiday full day event', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createWorkThisHoliday(daySchedules)
        httpBackend.flush()

  describe '#setSecondaryDayType', ->
    multiplier = {
      id: 1
    }
    expectedData = {
      "schedule_event": {
        "kind": "rest_day",
        "employee_id": 46,
        "day_event_date": "2015-02-03",
        "is_rest_day": true,
        "recurrence_info": {"type": "none"},
        "day_event_day_type_id": 1
      }
    }
    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule events', ->
      it 'posts one rest day type event', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.setSecondaryDayType(daySchedules, multiplier)
        httpBackend.flush()

  describe '#clearSchedule', ->
    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule Events', ->
      it 'does not do anything', ->
        subject.clearSchedule(daySchedules)

    describe 'when there is a non-recurring schedule', ->
      beforeEach ->
        setupSingleEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'deletes the schedule event', ->
        httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/51699?token=t0ken').respond(200)
        subject.clearSchedule(daySchedules)
        httpBackend.flush()

    describe 'when there is a recurring schedule', ->
      beforeEach ->
        setupRecurringEventResponse()
        setupScheduleEvents()
        daySchedules = new EmployeeScheduleDayList(day, employee,
          scheduleEvents)

      it 'inserts an exception into the recurring event', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events/51699/exceptions?token=t0ken',
          expectedExceptionJson)
        .respond({exceptions: ['2015-02-03']})
        subject.clearSchedule(daySchedules)
        httpBackend.flush()

  describe '#resetSchedule', ->
    beforeEach ->
      daySchedules = new EmployeeScheduleDayList(day, employee, [])

    describe 'when there are no schedule events', ->
      it 'does nothing', ->
        subject.resetSchedule(daySchedules)

      describe 'when there is a recurring schedule', ->
        beforeEach ->
          setupRecurringEventResponse()
          setupScheduleEvents()
          daySchedules = new EmployeeScheduleDayList(mtz('2015-02-10'), employee,
            scheduleEvents)

        it 'inserts an exception into the recurring event', ->
          httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/'+
            '51699/exceptions/2015-02-10?token=t0ken')
          .respond({exceptions: []})
          subject.resetSchedule(daySchedules)
          httpBackend.flush()


  describe '#createIndividualScheduleOnDay', ->
    exceptionInfo = {
      start: mtz('2015-02-03 07:00:00')
      end: mtz('2015-02-03 15:00:00')
      breaks: []
      tz: 'America/Vancouver'
      employeeId: 46
      worksiteId: 1
    }
    expectedData = {
      "schedule_event": {
        "kind": "single_shift",
        "shift_worksite_id": 1,
        "employee_id": 46,
        "is_rest_day": false,
        "shift_start_time": "2015-02-03T15:00:00.000Z",
        "shift_end_time": "2015-02-03T23:00:00.000Z",
        "shift_breaks": [],
        "recurrence_info": {"type": "none"}
      }
    }

    describe 'when there are no schedule Events', ->
      it 'posts ONE schedule', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createIndividualScheduleOnDay(day, [], exceptionInfo)
        httpBackend.flush()

    describe 'when trying to post an overnight shift', ->
      expectedOvernightData = {
        "schedule_event": {
          "kind": "single_shift",
          "shift_worksite_id": 1,
          "employee_id": 46,
          "is_rest_day": false,
          "shift_start_time": "2015-02-04T02:00:00.000Z",
          "shift_end_time": "2015-02-04T12:00:00.000Z",
          "shift_breaks": [],
          "recurrence_info": {"type": "none"}
        }
      }
      overnightExceptionInfo = {
        start: mtz('2015-02-03 18:00:00')
        end: mtz('2015-02-04 04:00:00')
        breaks: []
        tz: 'America/Vancouver'
        employeeId: 46
        worksiteId: 1
      }
      it 'posts the expected data', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedOvernightData).respond(200)
        subject.createIndividualScheduleOnDay(day, [], overnightExceptionInfo)
        httpBackend.flush()

    describe 'when there is a non-recurring schedule', ->
      beforeEach ->
        setupSingleEventResponse()
        setupScheduleEvents()

      it 'deletes the schedule event and then posts one schedule', ->
        httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/51699?token=t0ken').respond(200)
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createIndividualScheduleOnDay(day, scheduleEvents,
          exceptionInfo)
        httpBackend.flush()

      it 'deletes the schedule event and then posts one schedule even when the server responds 404', ->
        httpBackend.expectDELETE('http://api.payrollhero.dev/api/v4/schedule_events/51699?token=t0ken').respond(404)
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createIndividualScheduleOnDay(day, scheduleEvents,
          exceptionInfo)
        httpBackend.flush()

    describe 'when there is a recurring schedule', ->
      beforeEach ->
        setupRecurringEventResponse()
        setupScheduleEvents()

      it 'posts an exception to the recurrence and then adds the new exception', ->
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events/51699/exceptions?token=t0ken',
          expectedExceptionJson)
        .respond({exceptions: ['2015-02-03']})
        httpBackend.expectPOST('http://api.payrollhero.dev/api/v4/schedule_events?token=t0ken',
          expectedData).respond(200)
        subject.createIndividualScheduleOnDay(day, scheduleEvents,
          exceptionInfo)
        httpBackend.flush()

