/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

function run_test() {
  do_calendar_startup(really_run_test);
}

function really_run_test() {
  test_aclmanager();
  test_calendar();
  test_immutable();
  test_attendee();
  test_attachment();
  test_lastack();
  test_categories();
  test_alarm();
}

function test_aclmanager() {
  let mockCalendar = {
    QueryInterface: ChromeUtils.generateQI([Ci.calICalendar]),

    get superCalendar() {
      return this;
    },
    get aclManager() {
      return this;
    },

    getItemEntry(item) {
      if (item.id == "withentry") {
        return itemEntry;
      }
      return null;
    },
  };

  let itemEntry = {
    QueryInterface: ChromeUtils.generateQI([Ci.calIItemACLEntry]),
    userCanModify: true,
    userCanRespond: false,
    userCanViewAll: true,
    userCanViewDateAndTime: false,
  };

  let event = cal.createEvent();
  event.id = "withentry";
  event.calendar = mockCalendar;

  equal(event.aclEntry.userCanModify, itemEntry.userCanModify);
  equal(event.aclEntry.userCanRespond, itemEntry.userCanRespond);
  equal(event.aclEntry.userCanViewAll, itemEntry.userCanViewAll);
  equal(event.aclEntry.userCanViewDateAndTime, itemEntry.userCanViewDateAndTime);

  let parentEntry = cal.createEvent();
  parentEntry.id = "parententry";
  parentEntry.calendar = mockCalendar;
  parentEntry.parentItem = event;

  equal(parentEntry.aclEntry.userCanModify, itemEntry.userCanModify);
  equal(parentEntry.aclEntry.userCanRespond, itemEntry.userCanRespond);
  equal(parentEntry.aclEntry.userCanViewAll, itemEntry.userCanViewAll);
  equal(parentEntry.aclEntry.userCanViewDateAndTime, itemEntry.userCanViewDateAndTime);

  event = cal.createEvent();
  event.id = "noentry";
  event.calendar = mockCalendar;
  equal(event.aclEntry, null);
}

function test_calendar() {
  let event = cal.createEvent();
  let parentEntry = cal.createEvent();

  let mockCalendar = {
    QueryInterface: ChromeUtils.generateQI([Ci.calICalendar]),
    id: "one",
  };

  parentEntry.calendar = mockCalendar;
  event.parentItem = parentEntry;

  notEqual(event.calendar, null);
  equal(event.calendar.id, "one");
}

function test_attachment() {
  let e = cal.createEvent();

  let a = cal.createAttachment();
  a.rawData = "horst";

  let b = cal.createAttachment();
  b.rawData = "bruno";

  e.addAttachment(a);
  equal(e.getAttachments().length, 1);

  e.addAttachment(b);
  equal(e.getAttachments().length, 2);

  e.removeAttachment(a);
  equal(e.getAttachments().length, 1);

  e.removeAllAttachments();
  equal(e.getAttachments().length, 0);
}

function test_attendee() {
  let e = cal.createEvent();
  equal(e.getAttendeeById("unknown"), null);
  equal(e.getAttendees().length, 0);

  let a = cal.createAttendee();
  a.id = "mailto:horst";

  let b = cal.createAttendee();
  b.id = "mailto:bruno";

  e.addAttendee(a);
  equal(e.getAttendees().length, 1);
  equal(e.getAttendeeById("mailto:horst"), a);

  e.addAttendee(b);
  equal(e.getAttendees().length, 2);

  let comp = e.icalComponent;
  let aprop = comp.getFirstProperty("ATTENDEE");
  equal(aprop.value, "mailto:horst");
  aprop = comp.getNextProperty("ATTENDEE");
  equal(aprop.value, "mailto:bruno");
  equal(comp.getNextProperty("ATTENDEE"), null);

  e.removeAttendee(a);
  equal(e.getAttendees().length, 1);
  equal(e.getAttendeeById("mailto:horst"), null);

  e.removeAllAttendees();
  equal(e.getAttendees().length, 0);
}

function test_categories() {
  let e = cal.createEvent();

  equal(e.getCategories().length, 0);

  let cat = ["a", "b", "c"];
  e.setCategories(cat);

  cat[0] = "err";
  equal(e.getCategories().join(","), "a,b,c");

  let comp = e.icalComponent;
  let getter = comp.getFirstProperty.bind(comp);

  cat[0] = "a";
  while (cat.length) {
    equal(cat.shift(), getter("CATEGORIES").value);
    getter = comp.getNextProperty.bind(comp);
  }
}

function test_alarm() {
  let e = cal.createEvent();
  let alarm = cal.createAlarm();

  alarm.action = "DISPLAY";
  alarm.related = Ci.calIAlarm.ALARM_RELATED_ABSOLUTE;
  alarm.alarmDate = cal.createDateTime();

  e.addAlarm(alarm);
  let ecomp = e.icalComponent;
  let vcomp = ecomp.getFirstSubcomponent("VALARM");
  equal(vcomp.serializeToICS(), alarm.icalString);

  let alarm2 = alarm.clone();

  e.addAlarm(alarm2);

  equal(e.getAlarms().length, 2);
  e.deleteAlarm(alarm);
  equal(e.getAlarms().length, 1);
  equal(e.getAlarms()[0], alarm2);

  e.clearAlarms();
  equal(e.getAlarms().length, 0);
}

function test_immutable() {
  let event = cal.createEvent();

  let date = cal.createDateTime();
  date.timezone = cal.getTimezoneService().getTimezone("Europe/Berlin");
  event.alarmLastAck = date;

  let org = cal.createAttendee();
  org.id = "one";
  event.organizer = org;

  let alarm = cal.createAlarm();
  alarm.action = "DISPLAY";
  alarm.description = "foo";
  alarm.related = alarm.ALARM_RELATED_START;
  alarm.offset = cal.createDuration("PT1S");
  event.addAlarm(alarm);

  event.setProperty("X-NAME", "X-VALUE");
  event.setPropertyParameter("X-NAME", "X-PARAM", "X-PARAMVAL");

  event.setCategories(["a", "b", "c"]);

  equal(event.alarmLastAck.timezone.tzid, cal.dtz.UTC.tzid);

  event.makeImmutable();

  // call again, should not throw
  event.makeImmutable();

  ok(!event.alarmLastAck.isMutable);
  ok(!org.isMutable);
  ok(!alarm.isMutable);

  throws(() => {
    event.alarmLastAck = cal.createDateTime();
  }, /Can not modify immutable data container/);
  throws(() => {
    event.calendar = null;
  }, /Can not modify immutable data container/);
  throws(() => {
    event.parentItem = null;
  }, /Can not modify immutable data container/);
  throws(() => {
    event.setCategories(["d", "e", "f"]);
  }, /Can not modify immutable data container/);

  let event2 = event.clone();
  event2.organizer.id = "two";

  equal(org.id, "one");
  equal(event2.organizer.id, "two");

  equal(event2.getProperty("X-NAME"), "X-VALUE");
  equal(event2.getPropertyParameter("X-NAME", "X-PARAM"), "X-PARAMVAL");

  event2.setPropertyParameter("X-NAME", "X-PARAM", null);
  equal(event2.getPropertyParameter("X-NAME", "X-PARAM"), null);

  // TODO more clone checks
}

function test_lastack() {
  let e = cal.createEvent();

  e.alarmLastAck = cal.createDateTime("20120101T010101");

  // Our items don't support this yet
  //  equal(e.getProperty("X-MOZ-LASTACK"), "20120101T010101");

  let comp = e.icalComponent;
  let prop = comp.getFirstProperty("X-MOZ-LASTACK");

  equal(prop.value, "20120101T010101Z");

  prop.value = "20120101T010102Z";

  e.icalComponent = comp;

  equal(e.alarmLastAck.icalString, "20120101T010102Z");
}
