/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/

package org.ofbiz.workeffort.workeffort;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URISyntaxException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;
import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.data.ParserException;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.ComponentList;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.Dur;
import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.ParameterList;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.PropertyList;
import net.fortuna.ical4j.model.TimeZoneRegistry;
import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.component.VAlarm;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.component.VToDo;
import net.fortuna.ical4j.model.parameter.Cn;
import net.fortuna.ical4j.model.parameter.PartStat;
import net.fortuna.ical4j.model.parameter.XParameter;
import net.fortuna.ical4j.model.property.Action;
import net.fortuna.ical4j.model.property.Attendee;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.Clazz;
import net.fortuna.ical4j.model.property.Completed;
import net.fortuna.ical4j.model.property.Created;
import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.DtStamp;
import net.fortuna.ical4j.model.property.DtStart;
import net.fortuna.ical4j.model.property.Duration;
import net.fortuna.ical4j.model.property.LastModified;
import net.fortuna.ical4j.model.property.Location;
import net.fortuna.ical4j.model.property.Organizer;
import net.fortuna.ical4j.model.property.PercentComplete;
import net.fortuna.ical4j.model.property.Priority;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.Status;
import net.fortuna.ical4j.model.property.Summary;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.model.property.XProperty;

import org.ofbiz.base.util.DateRange;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.TimeDuration;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelParam;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;
import org.ofbiz.service.calendar.TemporalExpression;
import org.ofbiz.service.calendar.TemporalExpressionWorker;
import org.ofbiz.workeffort.workeffort.ICalWorker.ResponseProperties;

/** iCalendar converter class. This class uses the <a href="http://ical4j.sourceforge.net/index.html">
 * iCal4J</a> library.
 */
public class ICalConverter {

    protected static final String module = ICalConverter.class.getName();
    protected static final String partyIdXParamName = "X-ORG-APACHE-OFBIZ-PARTY-ID";
    protected static final ProdId prodId = new ProdId("-//Apache Open For Business//Work Effort Calendar//EN");
    protected static final String workEffortIdParamName = "X-ORG-APACHE-OFBIZ-WORKEFFORT-ID";
    protected static final String uidPrefix = "ORG-APACHE-OFBIZ-WE-";
    protected static final String workEffortIdXPropName = "X-ORG-APACHE-OFBIZ-WORKEFFORT-ID";
    protected static final String reminderXPropName = "X-ORG-APACHE-OFBIZ-REMINDER-ID";
    protected static final Map<String, String> fromStatusMap = UtilMisc.toMap("TENTATIVE", "CAL_TENTATIVE",
            "CONFIRMED", "CAL_CONFIRMED", "CANCELLED", "CAL_CANCELLED", "NEEDS-ACTION", "CAL_NEEDS_ACTION",
            "COMPLETED", "CAL_COMPLETED", "IN-PROCESS", "CAL_ACCEPTED");
    protected static final Map<String, Status> toStatusMap = UtilMisc.toMap("CAL_TENTATIVE", Status.VEVENT_TENTATIVE,
            "CAL_CONFIRMED", Status.VEVENT_CONFIRMED, "CAL_CANCELLED", Status.VEVENT_CANCELLED,
            "CAL_NEEDS_ACTION", Status.VTODO_NEEDS_ACTION, "CAL_COMPLETED", Status.VTODO_COMPLETED,
            "CAL_ACCEPTED", Status.VTODO_IN_PROCESS);
    protected static final Map<String, PartStat> toPartStatusMap = UtilMisc.toMap(
            "PRTYASGN_OFFERED", PartStat.TENTATIVE, "PRTYASGN_ASSIGNED", PartStat.ACCEPTED);
    protected static final Map<String, String> fromPartStatusMap = UtilMisc.toMap(
            "TENTATIVE", "PRTYASGN_OFFERED", "ACCEPTED", "PRTYASGN_ASSIGNED");
    protected static final Map<String, String> fromRoleMap = UtilMisc.toMap("ATTENDEE", "CAL_ATTENDEE",
            "CONTACT", "CONTACT", "ORGANIZER", "CAL_ORGANIZER");

    protected static VAlarm createAlarm(GenericValue workEffortEventReminder) {
        VAlarm alarm = null;
        Timestamp reminderStamp = workEffortEventReminder.getTimestamp("reminderDateTime");
        if (reminderStamp != null) {
            alarm = new VAlarm(new DateTime(reminderStamp));
        } else {
            TimeDuration duration = TimeDuration.fromNumber(workEffortEventReminder.getLong("reminderOffset"));
            alarm = new VAlarm(new Dur(duration.days(), duration.hours(), duration.minutes(), duration.seconds()));
        }
        return alarm;
    }

    protected static Attendee createAttendee(GenericValue partyValue, Map<String, Object> context) {
        Attendee attendee = new Attendee();
        loadPartyAssignment(attendee, partyValue, context);
        return attendee;
    }

    protected static Organizer createOrganizer(GenericValue partyValue, Map<String, Object> context) {
        Organizer organizer = new Organizer();
        loadPartyAssignment(organizer, partyValue, context);
        return organizer;
    }

    protected static ResponseProperties createWorkEffort(Component component, Map<String, Object> context) {
        Map<String, Object> serviceMap = FastMap.newInstance();
        setWorkEffortServiceMap(component, serviceMap);
        serviceMap.put("workEffortTypeId", "VTODO".equals(component.getName()) ? "TASK" : "EVENT");
        serviceMap.put("currentStatusId", "VTODO".equals(component.getName()) ? "CAL_NEEDS_ACTION" : "CAL_TENTATIVE");
        serviceMap.put("partyId", ((GenericValue) context.get("userLogin")).get("partyId"));
        serviceMap.put("roleTypeId", "CAL_OWNER");
        serviceMap.put("statusId", "PRTYASGN_ASSIGNED");
        Map<String, Object> serviceResult = invokeService("createWorkEffortAndPartyAssign", serviceMap, context);
        if (ServiceUtil.isError(serviceResult)) {
            return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult));
        }
        String workEffortId = (String) serviceResult.get("workEffortId");
        if (workEffortId != null) {
            replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId));
            serviceMap.clear();
            serviceMap.put("workEffortIdFrom", context.get("workEffortId"));
            serviceMap.put("workEffortIdTo", workEffortId);
            serviceMap.put("workEffortAssocTypeId", "WORK_EFF_DEPENDENCY");
            serviceMap.put("fromDate", new Timestamp(System.currentTimeMillis()));
            serviceResult = invokeService("createWorkEffortAssoc", serviceMap, context);
            if (ServiceUtil.isError(serviceResult)) {
                return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult));
            }
            storePartyAssignments(workEffortId, component, context);
        }
        return null;
    }

    protected static String fromClazz(PropertyList propertyList) {
        Clazz iCalObj = (Clazz) propertyList.getProperty(Clazz.CLASS);
        if (iCalObj == null) {
            return null;
        }
        return "WES_".concat(iCalObj.getValue());
    }

    protected static Timestamp fromCompleted(PropertyList propertyList) {
        Completed iCalObj = (Completed) propertyList.getProperty(Completed.COMPLETED);
        if (iCalObj == null) {
            return null;
        }
        Date date = iCalObj.getDate();
        return new Timestamp(date.getTime());
    }

    protected static String fromDescription(PropertyList propertyList) {
        Description iCalObj = (Description) propertyList.getProperty(Description.DESCRIPTION);
        if (iCalObj == null) {
            return null;
        }
        return iCalObj.getValue();
    }

    protected static Timestamp fromDtEnd(PropertyList propertyList) {
        DtEnd iCalObj = (DtEnd) propertyList.getProperty(DtEnd.DTEND);
        if (iCalObj == null) {
            return null;
        }
        Date date = iCalObj.getDate();
        return new Timestamp(date.getTime());
    }

    protected static Timestamp fromDtStart(PropertyList propertyList) {
        DtStart iCalObj = (DtStart) propertyList.getProperty(DtStart.DTSTART);
        if (iCalObj == null) {
            return null;
        }
        Date date = iCalObj.getDate();
        return new Timestamp(date.getTime());
    }

    protected static Double fromDuration(PropertyList propertyList) {
        Duration iCalObj = (Duration) propertyList.getProperty(Duration.DURATION);
        if (iCalObj == null) {
            return null;
        }
        Dur dur = iCalObj.getDuration();
        TimeDuration td = new TimeDuration(0, 0, (dur.getWeeks() * 7) + dur.getDays(), dur.getHours(), dur.getMinutes(), dur.getSeconds(), 0);
        return new Double(TimeDuration.toLong(td));
    }

    protected static Timestamp fromLastModified(PropertyList propertyList) {
        LastModified iCalObj = (LastModified) propertyList.getProperty(LastModified.LAST_MODIFIED);
        if (iCalObj == null) {
            return null;
        }
        Date date = iCalObj.getDate();
        return new Timestamp(date.getTime());
    }

    protected static String fromLocation(PropertyList propertyList) {
        Location iCalObj = (Location) propertyList.getProperty(Location.LOCATION);
        if (iCalObj == null) {
            return null;
        }
        return iCalObj.getValue();
    }

    protected static String fromParticipationStatus(Parameter status) {
        if (status == null) {
            return null;
        }
        return fromPartStatusMap.get(status.getValue());
    }

    protected static Long fromPercentComplete(PropertyList propertyList) {
        PercentComplete iCalObj = (PercentComplete) propertyList.getProperty(PercentComplete.PERCENT_COMPLETE);
        if (iCalObj == null) {
            return null;
        }
        return new Long(iCalObj.getPercentage());
    }

    protected static Double fromPriority(PropertyList propertyList) {
        Priority iCalObj = (Priority) propertyList.getProperty(Priority.PRIORITY);
        if (iCalObj == null) {
            return null;
        }
        return new Double(iCalObj.getLevel());
    }

    protected static String fromStatus(PropertyList propertyList) {
        Status iCalObj = (Status) propertyList.getProperty(Status.STATUS);
        if (iCalObj == null) {
            return null;
        }
        return fromStatusMap.get(iCalObj.getValue());
    }

    protected static String fromSummary(PropertyList propertyList) {
        Summary iCalObj = (Summary) propertyList.getProperty(Summary.SUMMARY);
        if (iCalObj == null) {
            return null;
        }
        return iCalObj.getValue();
    }

    protected static String fromUid(PropertyList propertyList) {
        Uid iCalObj = (Uid) propertyList.getProperty(Uid.UID);
        if (iCalObj == null) {
            return null;
        }
        return iCalObj.getValue();
    }

    protected static String fromXParameter(ParameterList parameterList, String parameterName) {
        if (parameterName == null) {
            return null;
        }
        Parameter parameter = parameterList.getParameter(parameterName);
        if (parameter != null) {
            return parameter.getValue();
        }
        return null;
    }

    protected static String fromXProperty(PropertyList propertyList, String propertyName) {
        if (propertyName == null) {
            return null;
        }
        Property property = propertyList.getProperty(propertyName);
        if (property != null) {
            return property.getValue();
        }
        return null;
    }

    protected static void getAlarms(GenericValue workEffort, ComponentList alarms) throws GenericEntityException {
        Description description = null;
        if (workEffort.get("description") != null) {
            description = new Description(workEffort.getString("description"));
        } else {
            description = new Description(workEffort.getString("workEffortName"));
        }
        Summary summary = new Summary(UtilProperties.getMessage("WorkEffortUiLabels", "WorkEffortEventReminder", Locale.getDefault()));
        Delegator delegator = workEffort.getDelegator();
        String workEffortId = workEffort.getString("workEffortId");
        List<GenericValue> reminderList = delegator.findList("WorkEffortEventReminder", EntityCondition.makeCondition("workEffortId", EntityOperator.EQUALS, workEffort.get("workEffortId")), null, null, null, false);
        for (GenericValue reminder : reminderList) {
            String reminderId = workEffortId + "-" + reminder.getString("sequenceId");
            VAlarm alarm = null;
            PropertyList alarmProps = null;
            boolean newAlarm = true;
            Iterator<VAlarm> i = UtilGenerics.cast(alarms.iterator());
            while (i.hasNext()) {
                alarm = i.next();
                Property xProperty = alarm.getProperty(reminderXPropName);
                if (xProperty != null && reminderId.equals(xProperty.getValue())) {
                    newAlarm = false;
                    alarmProps = alarm.getProperties();
                    // TODO: Write update code. For now, just re-create
                    alarmProps.clear();
                    break;
                }
            }
            if (newAlarm) {
                alarm = createAlarm(reminder);
                alarms.add(alarm);
                alarmProps = alarm.getProperties();
                alarmProps.add(new XProperty(reminderXPropName, reminderId));
            }
            GenericValue contactMech = reminder.getRelatedOne("ContactMech", false);
            if (contactMech != null && "EMAIL_ADDRESS".equals(contactMech.get("contactMechTypeId"))) {
                try {
                    alarmProps.add(new Attendee(contactMech.getString("infoString")));
                    alarmProps.add(Action.EMAIL);
                    alarmProps.add(summary);
                    alarmProps.add(description);
                } catch (URISyntaxException e) {
                    alarmProps.add(Action.DISPLAY);
                    alarmProps.add(new Description("Error encountered while creating iCalendar: " + e));
                }
            } else {
                alarmProps.add(Action.DISPLAY);
                alarmProps.add(description);
            }
            if (Debug.verboseOn()) {
                try {
                    alarm.validate(true);
                    Debug.logVerbose("iCalendar alarm passes validation", module);
                } catch (ValidationException e) {
                    Debug.logVerbose("iCalendar alarm fails validation: " + e, module);
                }
            }
        }
    }

    /** Returns a calendar derived from a Work Effort calendar publish point.
     * @param workEffortId ID of a work effort with <code>workEffortTypeId</code> equal to
     * <code>PUBLISH_PROPS</code>.
     * @param context The conversion context
     * @return An iCalendar as a <code>String</code>, or <code>null</code>
     * if <code>workEffortId</code> is invalid.
     * @throws GenericEntityException
     */
    public static ResponseProperties getICalendar(String workEffortId, Map<String, Object> context) throws GenericEntityException {
        Delegator delegator = (Delegator) context.get("delegator");
        GenericValue publishProperties = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false);
        if (!isCalendarPublished(publishProperties)) {
            Debug.logInfo("WorkEffort calendar is not published: " + workEffortId, module);
            return ICalWorker.createNotFoundResponse(null);
        }
        if (!"WES_PUBLIC".equals(publishProperties.get("scopeEnumId"))) {
            if (context.get("userLogin") == null) {
                return ICalWorker.createNotAuthorizedResponse(null);
            }
            if (!hasPermission(workEffortId, "VIEW", context)) {
                return ICalWorker.createForbiddenResponse(null);
            }
        }
        Calendar calendar = makeCalendar(publishProperties, context);
        ComponentList components = calendar.getComponents();
        List<GenericValue> workEfforts = getRelatedWorkEfforts(publishProperties, context);
        if (workEfforts != null) {
            for (GenericValue workEffort : workEfforts) {
                ResponseProperties responseProps = toCalendarComponent(components, workEffort, context);
                if (responseProps != null) {
                    return responseProps;
                }
            }
        }
        if (Debug.verboseOn()) {
            try {
                calendar.validate(true);
                Debug.logVerbose("iCalendar passes validation", module);
            } catch (ValidationException e) {
                Debug.logVerbose("iCalendar fails validation: " + e, module);
            }
        }
        return ICalWorker.createOkResponse(calendar.toString());
    }

    protected static void getPartyUrl(Property property, GenericValue partyAssign, Map<String, Object> context) {
        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("partyId", partyAssign.get("partyId"));
        Map<String, Object> resultMap = invokeService("getPartyICalUrl", serviceMap, context);
        String iCalUrl = (String) resultMap.get("iCalUrl");
        if (iCalUrl != null) {
            if (!iCalUrl.contains(":") && iCalUrl.contains("@")) {
                iCalUrl = "MAILTO:".concat(iCalUrl);
            }
            try {
                property.setValue(iCalUrl);
            } catch (Exception e) {
                Debug.logError(e, "Error while setting party URI: ", module);
            }
        }
    }

    protected static List<GenericValue> getRelatedWorkEfforts(GenericValue workEffort, Map<String, Object> context) throws GenericEntityException {
        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("workEffortId", workEffort.getString("workEffortId"));
        Map<String, Object> resultMap = invokeService("getICalWorkEfforts", serviceMap, context);
        List<GenericValue> workEfforts = UtilGenerics.checkList(resultMap.get("workEfforts"), GenericValue.class);
        if (workEfforts != null) {
            return WorkEffortWorker.removeDuplicateWorkEfforts(workEfforts);
        }
        return null;
    }

    protected static boolean hasPermission(String workEffortId, String action, Map<String, Object> context) {
        if (context.get("userLogin") == null) {
            return false;
        }
        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("workEffortId", workEffortId, "mainAction", action);
        Map<String, Object> serviceResult = invokeService("workEffortICalendarPermission", serviceMap, context);
        Boolean hasPermission = (Boolean) serviceResult.get("hasPermission");
        if (hasPermission != null) {
            return hasPermission.booleanValue();
        } else {
            return false;
        }
    }

    protected static Map<String, Object> invokeService(String serviceName, Map<String, ? extends Object> serviceMap, Map<String, Object> context) {
        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
        Map<String, Object> localMap = FastMap.newInstance();
        try {
            ModelService modelService = null;
            modelService = dispatcher.getDispatchContext().getModelService(serviceName);
            for (ModelParam modelParam: modelService.getInModelParamList()) {
                if (serviceMap.containsKey(modelParam.name)) {
                    Object value = serviceMap.get(modelParam.name);
                    if (UtilValidate.isNotEmpty(modelParam.type)) {
                        value = ObjectType.simpleTypeConvert(value, modelParam.type, null, null, null, true);
                    }
                    localMap.put(modelParam.name, value);
                }
            }
        } catch (Exception e) {
            String errMsg = "Error while creating service Map for service " + serviceName + ": ";
            Debug.logError(e, errMsg, module);
            return ServiceUtil.returnError(errMsg + e);
        }
        if (context.get("userLogin") != null) {
            localMap.put("userLogin", context.get("userLogin"));
        }
        localMap.put("locale", context.get("locale"));
        try {
            return dispatcher.runSync(serviceName, localMap);
        } catch (GenericServiceException e) {
            String errMsg = "Error while invoking service " + serviceName + ": ";
            Debug.logError(e, errMsg, module);
            return ServiceUtil.returnError(errMsg + e);
        }
    }

    protected static boolean isCalendarPublished(GenericValue publishProperties) {
        if (publishProperties == null || !"PUBLISH_PROPS".equals(publishProperties.get("workEffortTypeId"))) {
            return false;
        }
        DateRange range = new DateRange(publishProperties.getTimestamp("actualStartDate"), publishProperties.getTimestamp("actualCompletionDate"));
        return range.includesDate(new Date());
    }

    protected static void loadPartyAssignment(Property property, GenericValue partyAssign, Map<String, Object> context) {
        getPartyUrl(property, partyAssign, context);
        if (UtilValidate.isEmpty(property.getValue())) {
            try {
                // RFC 2445 4.8.4.1 and 4.8.4.3 Value must be a URL
                property.setValue("MAILTO:ofbiz-test@example.com");
            } catch (Exception e) {
                Debug.logError(e, "Error while setting Property value: ", module);
            }
        }
        ParameterList parameterList = property.getParameters();
        if (partyAssign != null) {
            replaceParameter(parameterList, toXParameter(partyIdXParamName, partyAssign.getString("partyId")));
            replaceParameter(parameterList, new Cn(makePartyName(partyAssign)));
            replaceParameter(parameterList, toParticipationStatus(partyAssign.getString("assignmentStatusId")));
        }
    }

    protected static void loadRelatedParties(List<GenericValue> relatedParties, PropertyList componentProps, Map<String, Object> context) {
        PropertyList attendees = componentProps.getProperties("ATTENDEE");
        for (GenericValue partyValue : relatedParties) {
            if ("CAL_ORGANIZER~CAL_OWNER".contains(partyValue.getString("roleTypeId"))) {
                // RFC 2445 4.6.1, 4.6.2, and 4.6.3 ORGANIZER can appear only once
                replaceProperty(componentProps, createOrganizer(partyValue, context));
            } else {
                String partyId = partyValue.getString("partyId");
                boolean newAttendee = true;
                Attendee attendee = null;
                Iterator<Attendee> i = UtilGenerics.cast(attendees.iterator());
                while (i.hasNext()) {
                    attendee = i.next();
                    Parameter xParameter = attendee.getParameter(partyIdXParamName);
                    if (xParameter != null && partyId.equals(xParameter.getValue())) {
                        loadPartyAssignment(attendee, partyValue, context);
                        newAttendee = false;
                        break;
                    }
                }
                if (newAttendee) {
                    attendee = createAttendee(partyValue, context);
                    componentProps.add(attendee);
                }
            }
        }
    }

    protected static void loadWorkEffort(PropertyList componentProps, GenericValue workEffort) {
        replaceProperty(componentProps, new DtStamp()); // iCalendar object created date/time
        replaceProperty(componentProps, toClazz(workEffort.getString("scopeEnumId")));
        replaceProperty(componentProps, toCreated(workEffort.getTimestamp("createdDate")));
        replaceProperty(componentProps, toDescription(workEffort.getString("description")));
        replaceProperty(componentProps, toDtStart(workEffort.getTimestamp("estimatedStartDate")));
        replaceProperty(componentProps, toLastModified(workEffort.getTimestamp("lastModifiedDate")));
        replaceProperty(componentProps, toPriority(workEffort.getLong("priority")));
        replaceProperty(componentProps, toLocation(workEffort.getString("locationDesc")));
        replaceProperty(componentProps, toStatus(workEffort.getString("currentStatusId")));
        replaceProperty(componentProps, toSummary(workEffort.getString("workEffortName")));
        Property uid = componentProps.getProperty(Uid.UID);
        if (uid == null) {
            // Don't overwrite UIDs created by calendar clients
            replaceProperty(componentProps, toUid(workEffort.getString("workEffortId")));
        }
        replaceProperty(componentProps, toXProperty(workEffortIdXPropName, workEffort.getString("workEffortId")));
    }

    protected static Calendar makeCalendar(GenericValue workEffort, Map<String, Object> context) throws GenericEntityException {
        String iCalData = null;
        GenericValue iCalValue = workEffort.getRelatedOne("WorkEffortIcalData", false);
        if (iCalValue != null) {
            iCalData = iCalValue.getString("icalData");
        }
        boolean newCalendar = true;
        Calendar calendar = null;
        if (iCalData == null) {
            Debug.logVerbose("iCalendar Data not found, creating new Calendar", module);
            calendar = new Calendar();
        } else {
            Debug.logVerbose("iCalendar Data found, using saved Calendar", module);
            StringReader reader = new StringReader(iCalData);
            CalendarBuilder builder = new CalendarBuilder();
            try {
                calendar = builder.build(reader);
                newCalendar = false;
            } catch (Exception e) {
                Debug.logError(e, "Error while parsing saved iCalendar, creating new iCalendar: ", module);
                calendar = new Calendar();
            }
        }
        PropertyList propList = calendar.getProperties();
        replaceProperty(propList, prodId);
        replaceProperty(propList, new XProperty(workEffortIdXPropName, workEffort.getString("workEffortId")));
        if (newCalendar) {
            propList.add(Version.VERSION_2_0);
            propList.add(CalScale.GREGORIAN);
            // TODO: Get time zone from publish properties value
            java.util.TimeZone tz = java.util.TimeZone.getDefault();
            TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
            net.fortuna.ical4j.model.TimeZone timezone = registry.getTimeZone(tz.getID());
            calendar.getComponents().add(timezone.getVTimeZone());
        }
        return calendar;
    }

    protected static String makePartyName(GenericValue partyAssign) {
        String partyName = partyAssign.getString("groupName");
        if (UtilValidate.isEmpty(partyName)) {
            partyName = partyAssign.getString("firstName") + " " + partyAssign.getString("lastName");
        }
        return partyName;
    }

    protected static void replaceParameter(ParameterList parameterList, Parameter parameter) {
        if (parameter == null) {
            return;
        }
        Parameter existingParam = parameterList.getParameter(parameter.getName());
        if (existingParam != null) {
            parameterList.remove(existingParam);
        }
        parameterList.add(parameter);
    }

    protected static void replaceProperty(PropertyList propertyList, Property property) {
        if (property == null) {
            return;
        }
        Property existingProp = propertyList.getProperty(property.getName());
        if (existingProp != null) {
            propertyList.remove(existingProp);
        }
        propertyList.add(property);
    }

    protected static void setMapElement(Map<String, Object> map, String key, Object value) {
        if (map == null || key == null || value == null) {
            return;
        }
        map.put(key, value);
    }

    protected static void setPartyIdFromUrl(Property property, Map<String, Object> context) {
        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("address", property.getValue(), "caseInsensitive", "Y");
        Map<String, Object> resultMap = invokeService("findPartyFromEmailAddress", serviceMap, context);
        String partyId = (String) resultMap.get("partyId");
        if (partyId != null) {
            replaceParameter(property.getParameters(), toXParameter(partyIdXParamName, partyId));
        }
    }

    protected static void setWorkEffortServiceMap(Component component, Map<String, Object> serviceMap) {
        PropertyList propertyList = component.getProperties();
        setMapElement(serviceMap, "scopeEnumId", fromClazz(propertyList));
        setMapElement(serviceMap, "description", fromDescription(propertyList));
        setMapElement(serviceMap, "locationDesc", fromLocation(propertyList));
        setMapElement(serviceMap, "priority", fromPriority(propertyList));
        setMapElement(serviceMap, "currentStatusId", fromStatus(propertyList));
        setMapElement(serviceMap, "workEffortName", fromSummary(propertyList));
        setMapElement(serviceMap, "universalId", fromUid(propertyList));
        // Set some fields to null so calendar clients can revert changes
        serviceMap.put("estimatedStartDate", null);
        serviceMap.put("estimatedCompletionDate", null);
        serviceMap.put("estimatedMilliSeconds", null);
        serviceMap.put("lastModifiedDate", null);
        serviceMap.put("actualCompletionDate", null);
        serviceMap.put("percentComplete", null);
        setMapElement(serviceMap, "estimatedStartDate", fromDtStart(propertyList));
        setMapElement(serviceMap, "estimatedMilliSeconds", fromDuration(propertyList));
        setMapElement(serviceMap, "lastModifiedDate", fromLastModified(propertyList));
        if ("VTODO".equals(component.getName())) {
            setMapElement(serviceMap, "actualCompletionDate", fromCompleted(propertyList));
            setMapElement(serviceMap, "percentComplete", fromPercentComplete(propertyList));
        } else {
            setMapElement(serviceMap, "estimatedCompletionDate", fromDtEnd(propertyList));
        }
    }

    /** Update work efforts from an incoming iCalendar request.
     * @param is
     * @param context
     * @throws IOException
     * @throws ParserException
     * @throws GenericEntityException
     * @throws GenericServiceException
     */
    public static ResponseProperties storeCalendar(InputStream is, Map<String, Object> context) throws IOException, ParserException, GenericEntityException, GenericServiceException {
        CalendarBuilder builder = new CalendarBuilder();
        Calendar calendar = null;
        try {
            calendar = builder.build(is);
        } finally {
            if (is != null) {
                is.close();
            }
        }
        if (Debug.verboseOn()) {
            Debug.logVerbose("Processing calendar:\r\n" + calendar, module);
        }
        String workEffortId = fromXProperty(calendar.getProperties(), workEffortIdXPropName);
        if (workEffortId == null) {
            workEffortId = (String) context.get("workEffortId");
        }
        if (!workEffortId.equals(context.get("workEffortId"))) {
            Debug.logWarning("Spoof attempt: received calendar workEffortId " + workEffortId +
                    " on URL workEffortId " + context.get("workEffortId"), module);
            return ICalWorker.createForbiddenResponse(null);
        }
        Delegator delegator = (Delegator) context.get("delegator");
        GenericValue publishProperties = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false);
        if (!isCalendarPublished(publishProperties)) {
            Debug.logInfo("WorkEffort calendar is not published: " + workEffortId, module);
            return ICalWorker.createNotFoundResponse(null);
        }
        if (context.get("userLogin") == null) {
            return ICalWorker.createNotAuthorizedResponse(null);
        }
        if (!hasPermission(workEffortId, "UPDATE", context)) {
            return ICalWorker.createForbiddenResponse(null);
        }
        boolean hasCreatePermission = hasPermission(workEffortId, "CREATE", context);
        List<GenericValue> workEfforts = getRelatedWorkEfforts(publishProperties, context);
        Set<String> validWorkEfforts = FastSet.newInstance();
        if (UtilValidate.isNotEmpty(workEfforts)) {
            // Security issue: make sure only related work efforts get updated
            for (GenericValue workEffort : workEfforts) {
                validWorkEfforts.add(workEffort.getString("workEffortId"));
            }
        }
        List<Component> components = UtilGenerics.checkList(calendar.getComponents(), Component.class);
        ResponseProperties responseProps = null;
        for (Component component : components) {
            if (Component.VEVENT.equals(component.getName()) || Component.VTODO.equals(component.getName())) {
                workEffortId = fromXProperty(component.getProperties(), workEffortIdXPropName);
                if (workEffortId == null) {
                    Property uid = component.getProperty(Uid.UID);
                    if (uid != null) {
                        GenericValue workEffort = EntityUtil.getFirst(delegator.findByAnd("WorkEffort", UtilMisc.toMap("universalId", uid.getValue()), null, false));
                        if (workEffort != null) {
                            workEffortId = workEffort.getString("workEffortId");
                        }
                    }
                }
                if (workEffortId != null) {
                    if (validWorkEfforts.contains(workEffortId)) {
                        replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId));
                        responseProps = storeWorkEffort(component, context);
                    } else {
                        Debug.logWarning("Spoof attempt: unrelated workEffortId " + workEffortId +
                                " on URL workEffortId " + context.get("workEffortId"), module);
                        responseProps = ICalWorker.createForbiddenResponse(null);
                    }
                } else if (hasCreatePermission) {
                    responseProps = createWorkEffort(component, context);
                }
                if (responseProps != null) {
                    return responseProps;
                }
            }
        }
        Map<String, ? extends Object> serviceMap = UtilMisc.toMap("workEffortId", context.get("workEffortId"), "icalData", calendar.toString());
        GenericValue iCalData = publishProperties.getRelatedOne("WorkEffortIcalData", false);
        Map<String, Object> serviceResult = null;
        if (iCalData == null) {
            serviceResult = invokeService("createWorkEffortICalData", serviceMap, context);
        } else {
            serviceResult = invokeService("updateWorkEffortICalData", serviceMap, context);
        }
        if (ServiceUtil.isError(serviceResult)) {
            return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult));
        }
        return ICalWorker.createOkResponse(null);
    }

    protected static ResponseProperties storePartyAssignments(String workEffortId, Component component, Map<String, Object> context) {
        ResponseProperties responseProps = null;
        Map<String, Object> serviceMap = FastMap.newInstance();
        List<Property> partyList = FastList.newInstance();
        partyList.addAll(UtilGenerics.checkList(component.getProperties("ATTENDEE"), Property.class));
        partyList.addAll(UtilGenerics.checkList(component.getProperties("CONTACT"), Property.class));
        partyList.addAll(UtilGenerics.checkList(component.getProperties("ORGANIZER"), Property.class));
        for (Property property : partyList) {
            String partyId = fromXParameter(property.getParameters(), partyIdXParamName);
            if (partyId == null) {
                serviceMap.clear();
                String address = property.getValue();
                if (address.toUpperCase().startsWith("MAILTO:")) {
                    address = address.substring(7);
                }
                serviceMap.put("address", address);
                Map<String, Object> result = invokeService("findPartyFromEmailAddress", serviceMap, context);
                partyId = (String) result.get("partyId");
                if (partyId == null) {
                    continue;
                }
                replaceParameter(property.getParameters(), toXParameter(partyIdXParamName, partyId));
            }
            serviceMap.clear();
            serviceMap.put("workEffortId", workEffortId);
            serviceMap.put("partyId", partyId);
            serviceMap.put("roleTypeId", fromRoleMap.get(property.getName()));
            Delegator delegator = (Delegator) context.get("delegator");
            List<GenericValue> assignments = null;
            try {
                assignments = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment", serviceMap, null, false));
                if (assignments.size() == 0) {
                    serviceMap.put("statusId", "PRTYASGN_OFFERED");
                    serviceMap.put("fromDate", new Timestamp(System.currentTimeMillis()));
                    invokeService("assignPartyToWorkEffort", serviceMap, context);
                }
            } catch (GenericEntityException e) {
                responseProps = ICalWorker.createPartialContentResponse(e.getMessage());
                break;
            }
        }
        return responseProps;
    }

    protected static ResponseProperties storeWorkEffort(Component component, Map<String, Object> context) throws GenericEntityException, GenericServiceException {
        PropertyList propertyList = component.getProperties();
        String workEffortId = fromXProperty(propertyList, workEffortIdXPropName);
        Delegator delegator = (Delegator) context.get("delegator");
        GenericValue workEffort = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false);
        if (workEffort == null) {
            return ICalWorker.createNotFoundResponse(null);
        }
        if (!hasPermission(workEffortId, "UPDATE", context)) {
            return null;
        }
        Map<String, Object> serviceMap = FastMap.newInstance();
        serviceMap.put("workEffortId", workEffortId);
        setWorkEffortServiceMap(component, serviceMap);
        invokeService("updateWorkEffort", serviceMap, context);
        return storePartyAssignments(workEffortId, component, context);
    }

    protected static ResponseProperties toCalendarComponent(ComponentList components, GenericValue workEffort, Map<String, Object> context) throws GenericEntityException {
        Delegator delegator = workEffort.getDelegator();
        String workEffortId = workEffort.getString("workEffortId");
        String workEffortUid = workEffort.getString("universalId");
        String workEffortTypeId = workEffort.getString("workEffortTypeId");
        GenericValue typeValue = delegator.findOne("WorkEffortType", UtilMisc.toMap("workEffortTypeId", workEffortTypeId), true);
        boolean isTask = false;
        boolean newComponent = true;
        ComponentList resultList = null;
        ComponentList alarms = null;
        Component result = null;
        if ("TASK".equals(workEffortTypeId) || (typeValue != null && "TASK".equals(typeValue.get("parentTypeId")))) {
            isTask = true;
            resultList = components.getComponents("VTODO");
        } else if ("EVENT".equals(workEffortTypeId) || (typeValue != null && "EVENT".equals(typeValue.get("parentTypeId")))) {
            resultList = components.getComponents("VEVENT");
        } else {
            return null;
        }
        Iterator<Component> i = UtilGenerics.cast(resultList.iterator());
        while (i.hasNext()) {
            result = i.next();
            Property xProperty = result.getProperty(workEffortIdXPropName);
            if (xProperty != null && workEffortId.equals(xProperty.getValue())) {
                newComponent = false;
                break;
            }
            Property uid = result.getProperty(Uid.UID);
            if (uid != null && uid.getValue().equals(workEffortUid)) {
                newComponent = false;
                break;
            }
        }
        if (isTask) {
            VToDo toDo = null;
            if (newComponent) {
                toDo = new VToDo();
                result = toDo;
            } else {
                toDo = (VToDo) result;
            }
            alarms = toDo.getAlarms();
        } else {
            VEvent event = null;
            if (newComponent) {
                event = new VEvent();
                result = event;
            } else {
                event = (VEvent) result;
            }
            alarms = event.getAlarms();
        }
        if (newComponent) {
            components.add(result);
        }
        PropertyList componentProps = result.getProperties();
        loadWorkEffort(componentProps, workEffort);
        if (isTask) {
            replaceProperty(componentProps, toCompleted(workEffort.getTimestamp("actualCompletionDate")));
            replaceProperty(componentProps, toPercentComplete(workEffort.getLong("percentComplete")));
        } else {
            replaceProperty(componentProps, toDtEnd(workEffort.getTimestamp("estimatedCompletionDate")));
        }
        if (workEffort.get("estimatedCompletionDate") == null) {
            replaceProperty(componentProps, toDuration(workEffort.getDouble("estimatedMilliSeconds")));
        }
        List<GenericValue> relatedParties = EntityUtil.filterByDate(delegator.findList("WorkEffortPartyAssignView", EntityCondition.makeCondition("workEffortId", EntityOperator.EQUALS, workEffortId), null, null, null, true));
        if (relatedParties.size() > 0) {
            loadRelatedParties(relatedParties, componentProps, context);
        }
        if (newComponent) {
            if (UtilValidate.isNotEmpty(workEffort.getString("tempExprId"))) {
                TemporalExpression tempExpr = TemporalExpressionWorker.getTemporalExpression(delegator, workEffort.getString("tempExprId"));
                if (tempExpr != null) {
                    try {
                        ICalRecurConverter.convert(tempExpr, componentProps);
                    } catch (Exception e) {
                        replaceProperty(componentProps, new Description("Error while converting recurrence: " + e));
                    }
                }
            }
            getAlarms(workEffort, alarms);
        }
        if (Debug.verboseOn()) {
            try {
                result.validate(true);
                Debug.logVerbose("iCalendar component passes validation", module);
            } catch (ValidationException e) {
                Debug.logVerbose(e, "iCalendar component fails validation: ", module);
            }
        }
        return null;
    }

    protected static Clazz toClazz(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Clazz(javaObj.replace("WES_", ""));
    }

    protected static Completed toCompleted(Timestamp javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Completed(new DateTime(javaObj));
    }

    protected static Created toCreated(Timestamp javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Created(new DateTime(javaObj));
    }

    protected static Description toDescription(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Description(javaObj);
    }

    protected static DtEnd toDtEnd(Timestamp javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new DtEnd(new DateTime(javaObj));
    }

    protected static DtStart toDtStart(Timestamp javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new DtStart(new DateTime(javaObj));
    }

    protected static Duration toDuration(Double javaObj) {
        if (javaObj == null) {
            return null;
        }
        TimeDuration duration = TimeDuration.fromNumber(javaObj);
        return new Duration(new Dur(duration.days(), duration.hours(), duration.minutes(), duration.seconds()));
    }

    protected static LastModified toLastModified(Timestamp javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new LastModified(new DateTime(javaObj));
    }

    protected static Location toLocation(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Location(javaObj);
    }

    protected static PartStat toParticipationStatus(String statusId) {
        if (statusId == null) {
            return null;
        }
        return toPartStatusMap.get(statusId);
    }

    protected static PercentComplete toPercentComplete(Long javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new PercentComplete(javaObj.intValue());
    }

    protected static Priority toPriority(Long javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Priority(javaObj.intValue());
    }

    protected static Status toStatus(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return toStatusMap.get(javaObj);
    }

    protected static Summary toSummary(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Summary(javaObj);
    }

    protected static Uid toUid(String javaObj) {
        if (javaObj == null) {
            return null;
        }
        return new Uid(uidPrefix.concat(javaObj));
    }

    protected static XParameter toXParameter(String name, String value) {
        if (name == null || value == null) {
            return null;
        }
        return new XParameter(name, value);
    }

    protected static XProperty toXProperty(String name, String value) {
        if (name == null || value == null) {
            return null;
        }
        return new XProperty(name, value);
    }
}
