require File.dirname(__FILE__) + "/../spec_helper"

describe :remaining_occurrences do
  it "should get the proper remaining occurrences from now" do
    start_time = Time.now
    end_time = Time.local(start_time.year, start_time.month, start_time.day, 23, 59, 59)
    schedule = Schedule.new(start_time)
    schedule.add_recurrence_rule(Rule.hourly.until(end_time))
    expect(schedule.remaining_occurrences(start_time).size).to eq(24 - schedule.start_time.hour)
  end

  it "should get the proper remaining occurrences past the end of the year" do
    start_time = Time.now
    schedule = Schedule.new(start_time)
    schedule.add_recurrence_rule(Rule.hourly.until(start_time + ONE_DAY))
    expect(schedule.remaining_occurrences(start_time + 366 * ONE_DAY).size).to eq(0)
  end

  it "should raise an error if there is nothing to stop it" do
    schedule = IceCube::Schedule.new
    schedule.add_recurrence_rule IceCube::Rule.daily
    expect { schedule.remaining_occurrences }.to raise_error ArgumentError
  end
end

describe :occurring_between? do
  let(:start_time) { Time.local(2012, 7, 7, 7) }
  let(:end_time) { start_time + 30 }

  let(:schedule) do
    IceCube::Schedule.new(start_time, duration: 30).tap do |schedule|
      schedule.rrule IceCube::Rule.daily
    end
  end

  it "should affirm an occurrence that spans the range exactly" do
    expect(schedule.occurring_between?(start_time, end_time)).to be_truthy
  end

  it "should affirm a zero-length occurrence at the start of the range" do
    schedule.duration = 0
    expect(schedule.occurring_between?(start_time, start_time)).to be_truthy
  end

  it "should deny a zero-length occurrence at the end of the range" do
    schedule.duration = 0
    expect(schedule.occurring_between?(end_time, end_time)).to be_falsey
  end

  it "should affirm an occurrence entirely contained within the range" do
    expect(schedule.occurring_between?(start_time + 1, end_time - 1)).to be_truthy
  end

  it "should affirm an occurrence spanning across the start of the range" do
    expect(schedule.occurring_between?(start_time - 1, start_time + 1)).to be_truthy
  end

  it "should affirm an occurrence spanning across the end of the range" do
    expect(schedule.occurring_between?(end_time - 1, end_time + 1)).to be_truthy
  end

  it "should affirm an occurrence spanning across the range entirely" do
    expect(schedule.occurring_between?(start_time - 1, end_time + 1)).to be_truthy
  end

  it "should deny an occurrence before the range" do
    expect(schedule.occurring_between?(end_time + 1, end_time + 2)).to be_falsey
  end

  it "should deny an occurrence after the range" do
    expect(schedule.occurring_between?(start_time - 2, start_time - 1)).to be_falsey
  end
end

describe :next_occurrence do
  it "should get the next occurrence from now" do
    start_time = Time.local(2010, 10, 10, 10, 0, 0)
    schedule = Schedule.new(start_time, end_time: start_time + 24 * ONE_HOUR)
    schedule.add_recurrence_rule(Rule.hourly)
    expect(schedule.next_occurrence(schedule.start_time)).to eq(schedule.start_time + 1 * ONE_HOUR)
  end

  it "should get the next occurrence past the end of the year" do
    start_time = Time.now
    schedule = Schedule.new(start_time, end_time: start_time + 24 * ONE_HOUR)
    schedule.add_recurrence_rule(Rule.hourly)
    expect(schedule.next_occurrence(schedule.end_time + 366 * ONE_DAY)).to eq(schedule.end_time + 366 * ONE_DAY + 1 * ONE_HOUR)
  end

  it "should be able to use next_occurrence on a never-ending schedule" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_rule Rule.hourly
    expect(schedule.next_occurrence(schedule.start_time)).to eq(schedule.start_time + ONE_HOUR)
  end

  it "should get the next occurrence when a recurrence date is also added" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_time(schedule.start_time + 30 * ONE_MINUTE)
    schedule.add_recurrence_rule Rule.hourly
    expect(schedule.next_occurrence(schedule.start_time)).to eq(schedule.start_time + 30 * ONE_MINUTE)
  end

  it "should get the next occurrence and ignore recurrence dates that are before the desired time" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_time(schedule.start_time + 30 * ONE_MINUTE)
    schedule.add_recurrence_time(schedule.start_time - 30 * ONE_MINUTE)
    schedule.add_recurrence_rule Rule.hourly
    expect(schedule.next_occurrence(schedule.start_time)).to eq(schedule.start_time + 30 * ONE_MINUTE)
  end
end

describe :next_occurrences do
  it "should get the next 3 occurrence from now" do
    start_time = Time.local(2010, 1, 1, 10, 0, 0)
    schedule = Schedule.new(start_time, end_time: start_time + ONE_HOUR * 24)
    schedule.add_recurrence_rule(Rule.hourly)
    expect(schedule.next_occurrences(3, start_time)).to eq([
      schedule.start_time + 1 * ONE_HOUR,
      schedule.start_time + 2 * ONE_HOUR,
      schedule.start_time + 3 * ONE_HOUR
    ])
  end

  it "should get the next 3 occurrence past the end of the year" do
    schedule = Schedule.new(Time.now, end_time: Time.now + ONE_HOUR * 24)
    schedule.add_recurrence_rule(Rule.hourly.until(Time.now + 365 * ONE_DAY))
    expect(schedule.next_occurrences(3, schedule.end_time + 366 * ONE_DAY)).to eq([])
  end

  it "should be able to use next_occurrences on a never-ending schedule" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_rule Rule.hourly
    expect(schedule.next_occurrences(3, schedule.start_time)).to eq([
      schedule.start_time + 1 * ONE_HOUR,
      schedule.start_time + 2 * ONE_HOUR,
      schedule.start_time + 3 * ONE_HOUR
    ])
  end

  it "should get the next 3 occurrences when a recurrence date is also added" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_rule Rule.hourly
    schedule.add_recurrence_time(schedule.start_time + 30 * ONE_MINUTE)
    expect(schedule.next_occurrences(3, schedule.start_time)).to eq([
      schedule.start_time + 30 * ONE_MINUTE,
      schedule.start_time + 1 * ONE_HOUR,
      schedule.start_time + 2 * ONE_HOUR
    ])
  end

  it "should get the next 3 occurrences and ignore recurrence dates that are before the desired time" do
    schedule = Schedule.new(Time.now)
    schedule.add_recurrence_time(schedule.start_time + 30 * ONE_MINUTE)
    schedule.add_recurrence_time(schedule.start_time - 30 * ONE_MINUTE)
    schedule.add_recurrence_rule Rule.hourly
    expect(schedule.next_occurrences(3, schedule.start_time)).to eq([
      schedule.start_time + 30 * ONE_MINUTE,
      schedule.start_time + ONE_HOUR,
      schedule.start_time + ONE_HOUR * 2
    ])
  end

  it "should generate the same comparable time objects (down to millisecond) on two runs" do
    schedule = Schedule.new Time.now
    schedule.rrule Rule.daily
    expect(schedule.next_occurrences(5)).to eq(schedule.next_occurrences(5))
  end
end
