﻿//-----------------------------------------------------------------------------
// XCalEvent
//
// Copyright 2005-2010 - Xcential Group LLC.
//
//-----------------------------------------------------------------------------

XCalEvent.prototype = new XNode;
XCalEvent.prototype.constructor = XCalEvent;

//=============================================================================
// Constructor

function XCalEvent(
   refOrItem,
   create
)
{
   refOrItem = (refOrItem == null) ? null : refOrItem;
   create = (create == null) ? true : false;

   if (create)
      return new XCalEvent(refOrItem, false);

   //--------------------------------------------------------------------------
   // Private Interface

   //--------------------------------------------------------------------------
   // Privileged Interface

   this.valueOf = function()
   {

      return oNode;
   }

   //--------------------------------------------------------------------------

   this.setObjectValue = function(
      refOrItem
   )
   {
      refOrItem = (refOrItem == null) ? null : refOrItem;

      oNode = XNode.getNodeFrom(refOrItem);

      return oNode;
   }

   //--------------------------------------------------------------------------
   // Initialization

   var oNode = this.setObjectValue(refOrItem);
}

XCalEvent.prototype.objectClass = "XCalEvent";

//=============================================================================
// Static Interface

XCalEvent.CLASS_PUBLIC       = "public";
XCalEvent.CLASS_PRIVATE      = "private";
XCalEvent.CLASS_CONFIDENTIAL = "confidential";

XCalEvent.TRANSP_TRANSPARENT = "transparent";
XCalEvent.TRANSP_OPAQUE      = "opaque";

XCalEvent.STATUS_TENTATIVE = "tentative";
XCalEvent.STATUS_CONFIRMED = "confirmed";
XCalEvent.STATUS_CANCELLED = "cancelled";

//=============================================================================
// Public Interface

XCalEvent.prototype.init = function(
   id,
   timestamp,
   startsAt,
   endsAt,
   duration,
   className,
   transp,
   status,
   priority
)
{
   id = (id == null) ? XUtils.generateId("urn:xcential-com:calevent:", XUtils.SCHEME_GUID) : id;
   timestamp = (timestamp == null) ? XDate().toString(XDate.STYLE_ICALZ) : timestamp;
   endsAt = (endsAt == null) ? null : XDate(endsAt).toString(XDate.STYLE_TIMESTAMP);
   duration = (duration == null) ? null : duration;
   className = (className == null) ? XCalEvent.CLASS_PUBLIC : className;
   transp = (transp == null) ? XCalEvent.TRANSP_OPAQUE : transp;
   status = (status == null) ? XCalEvent.STATUS_TENTATIVE : status;
   priority = (priority == null) ? 0 : priority; // 0 = Undefined, 1 = highest, 9 = lowest

   var node = this.valueOf();

   node.setAttribute("id", id);
   node.setAttribute("timestamp", timestamp);
   node.setAttribute("startsAt", startsAt);
   if (endsAt)
      node.setAttribute("endsAt", endsAt);
   if (duration)
      node.setAttribute("duration", duration);
   node.setAttribute("class", className);
   node.setAttribute("trans", transp);
   node.setAttribute("status", status);
   node.setAttribute("priority", priority);

}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getId = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var id = node.getAttribute("id");

   return (XString(id).isNothing()) ? null : (castAs == null) ? id : castAs(id);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getDocId = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var docId = this.getXDoc().getRoot().getChildValue("identifier");

   return (XString(docId).isNothing()) ? null : (castAs == null) ? docId : castAs(docId);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getStartsAt = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var startsAt = node.getAttribute("startsAt");

   return (XString(startsAt).isNothing()) ? null : (castAs == null) ? startsAt : castAs(startsAt);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getEndsAt = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var endsAt = node.getAttribute("endsAt");
   if (XString(endsAt).isNothing())
   {
      var startsAt = node.getAttribute("startsAt");
      var duration = this.getDuration();
      if (XString(duration).isSomething())
      {
         if (XMatch(duration, /^P([0-9]+)D$/i))
         {
            duration = Number(XMatch.matches[1]);
            endsAt = XDate((XDate(startsAt)).valueOf().valueOf() + (duration*24*60*60*1000-1000)).toString(XDate.STYLE_YYYY_MM_DD);
         }
         else
            endsAt = startsAt;
      }
      else
         endsAt = startsAt;
   }

   return (XString(endsAt).isNothing()) ? null : (castAs == null) ? endsAt : castAs(endsAt);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getDuration = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var duration = node.getAttribute("duration");

   return (XString(duration).isNothing()) ? null : (castAs == null) ? duration : castAs(duration);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getTransp = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var transp = node.getAttribute("transp");

   return (XString(transp).isNothing()) ? XCalEvent.TRANSP_OPAQUE : (castAs == null) ? transp : castAs(transp);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getStatus = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var status = node.getAttribute("status");

   return (XString(status).isNothing()) ? XCalEvent.STATUS_TENTATIVE : (castAs == null) ? status : castAs(status);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getPriority = function(
   castAs
)
{
   castAs = (castAs == null) ? null : castAs;

   var node = this.valueOf();
   var priority = node.getAttribute("priority");

   return (XString(priority).isNothing()) ? 0 : (castAs == null) ? Number(priority) : castAs(priority);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getLocation = function()
{

   return this.getChildValue("location");
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.setLocation = function(
   location
)
{

   var locationXNode = this.X$("xcal:location");
   if (!locationXNode)
   {
      locationXNode = this.getXDoc().createNode(XNode.NODE_ELEMENT, "location", XCalDoc.NAMESPACE_URI);
      var addBefore = this.X$("./xcal:summary|./xcal:description|./xcal:comment|./xcal:category|./xcal:attachment");
      this.addChild(locationXNode, addBefore);
   }
   locationXNode.setText(location);

   return locationXNode;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getSummary = function()
{

   return this.getChildValue("summary");
}

//-----------------------------------------------------------------------------
XCalEvent.prototype.setSummary = function(
   summary
)
{
   summary = (summary == null) ? "" : summary.toString();

   // Summaries are limited to 255 characters by the ICS format. Try various
   // strategies to stay within that.
   if (summary.length > 255)
   {
      while (summary.length > 200 && XMatch(summary, /\s+\([^\)]*\)([^\(]*)$/))
         summary = XMatch.leftContext + XMatch.matches[1];
      if (summary.length > 255)
         summary = summary.substr(0,252) + "...";
   }

   var summaryXNode = this.X$("xcal:summary");
   if (!summaryXNode)
   {
      summaryXNode = this.getXDoc().createNode(XNode.NODE_ELEMENT, "summary", XCalDoc.NAMESPACE_URI);
      var addBefore = this.X$("./xcal:description|./xcal:comment|./xcal:category|./xcal:attachment");
      this.addChild(summaryXNode, addBefore);
   }
   summaryXNode.setText(summary);

   return summaryXNode;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getDescription = function(
   descType
)
{

   var descriptionXNode = this.X$("./xcal:description" + ((XString(descType).isSomething()) ? "[@type='" + descType + "']" : "[not(@type)]"));


   return (descriptionXNode) ? descriptionXNode.getXML(XNode.INNER_ONLY) : null;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.setDescription = function(
   descType,
   description
)
{
   descType = (descType == null) ? null : descType;

   var descriptionXNode = this.X$("./xcal:description" + ((XString(descType).isSomething()) ? "[@type='" + descType + "']" : "[not(@type)]"));
   if (!descriptionXNode)
   {
      descriptionXNode = this.getXDoc().createNode(XNode.NODE_ELEMENT, "description", XCalDoc.NAMESPACE_URI);
      var addBefore = this.X$("./xcal:comment|./xcal:category|./xcal:attachment");
      this.addChild(descriptionXNode, addBefore);
      if (descType)
         descriptionXNode.setAttribute("type", descType);
   }

   if (!descType)
      descriptionXNode.setText(description);
   else
      descriptionXNode.setXML("<description xmlns=\"" + XCalDoc.NAMESPACE_URI + "\" type=\"" + descType + "\">" + description + "</description>");

   return descriptionXNode;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.appendDescription = function(
   descType,
   description
)
{
   descType = (descType == null) ? null : descType;

   var currentDescription = this.getDescription(descType);
   description = ((XString(currentDescription).isSomething()) ? currentDescription : "") + description;

   return this.setDescription(descType, description);
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getCategories = function()
{

   var categories = new Array();
   var categoryXNodes = this.X$$("./xcal:category");
   for (var i=0; i<categoryXNodes.length; i++)
      categories.push(categoryXNodes.X$(i).toText());

   return categories;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.addCategory = function(
   category
)
{

   var categoryXNode = this.getXDoc().createNode(XNode.NODE_ELEMENT, "category", XCalDoc.NAMESPACE_URI);
   this.addChild(categoryXNode, this.X$("xcal:attachment"));
   categoryXNode.setText(category);

   return categoryXNode;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.isHoliday = function()
{

   var categories = this.getCategories();
   for (j=0; j<categories.length; j++)
   {
      var category = categories[j];
      if (category == "Holiday")
         return true;
   }

   return false;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.getAttachments = function()
{

   var attachments = new Array();
   var attachmentXNodes = this.X$$("./xcal:attachment");
   for (var i=0; i<attachmentXNodes.length; i++)
   {
      var attachmentXNode = attachmentXNodes.X$(1);
      var attachment = new Array();
      attachment.type = attachmentXNode.getAttribute("type");
      attachment.ref = attachmentXNode.getAttribute("href");
      attachments.push(attachment);
   }

   return attachments;
}

//-----------------------------------------------------------------------------

XCalEvent.prototype.addAttachment = function(
   type,
   ref,
   title
)
{
   type = (type == null) ? "text" : type;
   title = (title == null) ? null : title;

   var attachmentXNode = this.getXDoc().createNode(XNode.NODE_ELEMENT, "attachment", XCalDoc.NAMESPACE_URI)
   this.addChild(attachmentXNode);
   attachmentXNode.setAttribute("type", type);
   attachmentXNode.setAttribute("href", ref);
   if (XString(title).isSomething())
      attachmentXNode.setAttribute("title", title)

   return attachmentXNode;
}

//=============================================================================


