require File.dirname(__FILE__) + '/../spec_helper'
require 'active_support/time'

describe IceCube, 'to_ical' do

  it 'should return a proper ical representation for a basic daily rule' do
    rule = IceCube::Rule.daily
    expect(rule.to_ical).to eq("FREQ=DAILY")
  end

  it 'should return a proper ical representation for a basic monthly rule' do
    rule = IceCube::Rule.weekly
    expect(rule.to_ical).to eq("FREQ=WEEKLY")
  end

  it 'should return a proper ical representation for a basic monthly rule' do
    rule = IceCube::Rule.monthly
    expect(rule.to_ical).to eq("FREQ=MONTHLY")
  end

  it 'should return a proper ical representation for a basic yearly rule' do
    rule = IceCube::Rule.yearly
    expect(rule.to_ical).to eq("FREQ=YEARLY")
  end

  it 'should return a proper ical representation for a basic hourly rule' do
    rule = IceCube::Rule.hourly
    expect(rule.to_ical).to eq("FREQ=HOURLY")
  end

  it 'should return a proper ical representation for a basic minutely rule' do
    rule = IceCube::Rule.minutely
    expect(rule.to_ical).to eq("FREQ=MINUTELY")
  end

  it 'should return a proper ical representation for a basic secondly rule' do
    rule = IceCube::Rule.secondly
    expect(rule.to_ical).to eq("FREQ=SECONDLY")
  end

  it 'should be able to serialize a .day rule to_ical' do
    rule = IceCube::Rule.daily.day(:monday, :tuesday)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYDAY=MO,TU")
  end

  it 'should be able to serialize a .day_of_week rule to_ical' do
    rule = IceCube::Rule.daily.day_of_week(:tuesday => [-1, -2])
    expect(rule.to_ical).to eq("FREQ=DAILY;BYDAY=-1TU,-2TU")
  end

  it 'should be able to serialize a .day_of_month rule to_ical' do
    rule = IceCube::Rule.daily.day_of_month(23)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYMONTHDAY=23")
  end

  it 'should be able to serialize a .day_of_year rule to_ical' do
    rule = IceCube::Rule.yearly.day_of_year(100,200)
    expect(rule.to_ical).to eq("FREQ=YEARLY;BYYEARDAY=100,200")
  end

  it 'should be able to serialize a .month_of_year rule to_ical' do
    rule = IceCube::Rule.daily.month_of_year(:january, :april)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYMONTH=1,4")
  end

  it 'should be able to serialize a .hour_of_day rule to_ical' do
    rule = IceCube::Rule.daily.hour_of_day(10, 20)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYHOUR=10,20")
  end

  it 'should be able to serialize a .minute_of_hour rule to_ical' do
    rule = IceCube::Rule.daily.minute_of_hour(5, 55)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYMINUTE=5,55")
  end

  it 'should be able to serialize a .second_of_minute rule to_ical' do
    rule = IceCube::Rule.daily.second_of_minute(0, 15, 30, 45)
    expect(rule.to_ical).to eq("FREQ=DAILY;BYSECOND=0,15,30,45")
  end

  it 'should be able to collapse a combination day_of_week and day' do
    rule = IceCube::Rule.daily.day(:monday, :tuesday).day_of_week(:monday => [1, -1])
    expect(['FREQ=DAILY;BYDAY=TU,1MO,-1MO', 'FREQ=DAILY;BYDAY=1MO,-1MO,TU'].include?(rule.to_ical)).to be_truthy
  end

  it 'should be able to serialize of .day_of_week rule to_ical with multiple days' do
    rule = IceCube::Rule.daily.day_of_week(:monday => [1, -1], :tuesday => [2]).day(:wednesday)
    expect([
      'FREQ=DAILY;BYDAY=WE,1MO,-1MO,2TU',
      'FREQ=DAILY;BYDAY=1MO,-1MO,2TU,WE',
      'FREQ=DAILY;BYDAY=2TU,1MO,-1MO,WE',
      'FREQ=DAILY;BYDAY=WE,2TU,1MO,-1MO',
      'FREQ=DAILY;BYDAY=2TU,WE,1MO,-1MO'
    ].include?(rule.to_ical)).to be_truthy
  end

  it 'should be able to serialize a base schedule to ical in local time' do
    Time.zone = "Eastern Time (US & Canada)"
    schedule = IceCube::Schedule.new(Time.zone.local(2010, 5, 10, 9, 0, 0))
    expect(schedule.to_ical).to eq("DTSTART;TZID=EDT:20100510T090000")
  end

  it 'should be able to serialize a base schedule to ical in UTC time' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 9, 0, 0))
    expect(schedule.to_ical).to eq("DTSTART:20100510T090000Z")
  end

  it 'should be able to serialize a schedule with one rrule' do
    Time.zone = 'Pacific Time (US & Canada)'
    schedule = IceCube::Schedule.new(Time.zone.local(2010, 5, 10, 9, 0, 0))
    schedule.add_recurrence_rule IceCube::Rule.weekly
    # test equality
    expectation = "DTSTART;TZID=PDT:20100510T090000\n"
    expectation << 'RRULE:FREQ=WEEKLY'
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with multiple rrules' do
    Time.zone = 'Eastern Time (US & Canada)'
    schedule = IceCube::Schedule.new(Time.zone.local(2010, 10, 20, 4, 30, 0))
    schedule.add_recurrence_rule IceCube::Rule.weekly.day_of_week(:monday => [2, -1])
    schedule.add_recurrence_rule IceCube::Rule.hourly
    expectation = "DTSTART;TZID=EDT:20101020T043000\n"
    expectation << "RRULE:FREQ=WEEKLY;BYDAY=2MO,-1MO\n"
    expectation << "RRULE:FREQ=HOURLY"
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with one exrule' do
    Time.zone ='Pacific Time (US & Canada)'
    schedule = IceCube::Schedule.new(Time.zone.local(2010, 5, 10, 9, 0, 0))
    schedule.add_exception_rule IceCube::Rule.weekly
    # test equality
    expectation= "DTSTART;TZID=PDT:20100510T090000\n"
    expectation<< 'EXRULE:FREQ=WEEKLY'
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with multiple exrules' do
    Time.zone ='Eastern Time (US & Canada)'
    schedule = IceCube::Schedule.new(Time.zone.local(2010, 10, 20, 4, 30, 0))
    schedule.add_exception_rule IceCube::Rule.weekly.day_of_week(:monday => [2, -1])
    schedule.add_exception_rule IceCube::Rule.hourly
    expectation = "DTSTART;TZID=EDT:20101020T043000\n"
    expectation<< "EXRULE:FREQ=WEEKLY;BYDAY=2MO,-1MO\n"
    expectation<< "EXRULE:FREQ=HOURLY"
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with an rtime' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 10, 0, 0))
    schedule.add_recurrence_time Time.utc(2010, 6, 20, 5, 0, 0)
    # test equality
    expectation = "DTSTART:20100510T100000Z\n"
    expectation << "RDATE:20100620T050000Z"
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with an exception time' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 10, 0, 0))
    schedule.add_exception_time Time.utc(2010, 6, 20, 5, 0, 0)
    # test equality
    expectation = "DTSTART:20100510T100000Z\n"
    expectation << "EXDATE:20100620T050000Z"
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with a duration' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 10), :duration => 3600)
    expectation = "DTSTART:20100510T100000Z\n"
    expectation << 'DTEND:20100510T110000Z'
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with a duration - more odd duration' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 10), :duration => 3665)
    expectation = "DTSTART:20100510T100000Z\n"
    expectation << 'DTEND:20100510T110105Z'
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should be able to serialize a schedule with an end time' do
    schedule = IceCube::Schedule.new(Time.utc(2010, 5, 10, 10), :end_time => Time.utc(2010, 5, 10, 20))
    expectation = "DTSTART:20100510T100000Z\n"
    expectation << "DTEND:20100510T200000Z"
    expect(schedule.to_ical).to eq(expectation)
  end

  it 'should not modify the duration when running to_ical' do
    schedule = IceCube::Schedule.new(Time.now, :duration => 3600)
    schedule.to_ical
    expect(schedule.duration).to eq(3600)
  end

  it 'should default to to_ical using local time' do
    time = Time.now
    schedule = IceCube::Schedule.new(Time.now)
    expect(schedule.to_ical).to eq("DTSTART;TZID=#{time.zone}:#{time.strftime('%Y%m%dT%H%M%S')}") # default false
  end

  it 'should not have an rtime that duplicates start time' do
    start = Time.utc(2012, 12, 12, 12, 0, 0)
    schedule = IceCube::Schedule.new(start)
    schedule.add_recurrence_time start
    expect(schedule.to_ical).to eq("DTSTART:20121212T120000Z")
  end

  it 'should be able to receive a to_ical in utc time' do
    time = Time.now
    schedule = IceCube::Schedule.new(Time.now)
    expect(schedule.to_ical).to eq("DTSTART;TZID=#{time.zone}:#{time.strftime('%Y%m%dT%H%M%S')}") # default false
    expect(schedule.to_ical(false)).to eq("DTSTART;TZID=#{time.zone}:#{time.strftime('%Y%m%dT%H%M%S')}")
    expect(schedule.to_ical(true)).to  eq("DTSTART:#{time.utc.strftime('%Y%m%dT%H%M%S')}Z")
  end

  it 'should be able to serialize to ical with an until date' do
    rule = IceCube::Rule.weekly.until Time.utc(2123, 12, 31, 12, 34, 56.25)
    expect(rule.to_ical).to match "FREQ=WEEKLY;UNTIL=21231231T123456Z"
  end

  it 'should be able to serialize to ical with a count date' do
    rule = IceCube::Rule.weekly.count(5)
    expect(rule.to_ical).to eq "FREQ=WEEKLY;COUNT=5"
  end

  %w{secondly minutely hourly daily monthly yearly}.each do |mthd|
    it "should include intervals for #{mthd} rule" do
      interval = 2
      rule = IceCube::Rule.send(mthd.to_sym, interval)
      expect(rule.to_ical).to eq("FREQ=#{mthd.upcase};INTERVAL=#{interval}")
    end
  end

  it 'should include intervals for weekly rule, including weekstart' do
    interval = 2
    rule = IceCube::Rule.send(:weekly, interval)
    expect(rule.to_ical).to eq("FREQ=WEEKLY;INTERVAL=#{interval};WKST=SU")
  end

  it 'should include intervals for weekly rule, including custom weekstart' do
    interval = 2
    rule = IceCube::Rule.send(:weekly, interval, :monday)
    expect(rule.to_ical).to eq("FREQ=WEEKLY;INTERVAL=#{interval};WKST=MO")
  end

  it 'should not repeat interval when updating rule' do
    rule = IceCube::Rule.weekly
    rule.interval(2)
    expect(rule.to_ical).to match(/^FREQ=WEEKLY;INTERVAL=2/)
  end

end
