// -----------------------------------------------------------------------------
// CPIMAgnToDoAdapter::AddDefaultValuesToEntryL
// (other items were commented in a header)
// -----------------------------------------------------------------------------
//
void CPIMAgnToDoAdapter::AddDefaultValuesToEntryL(const MPIMItemData& aData,
        CCalEntry& aEntry) const
{
    JELOG2(EPim);
    // Calendar creates medium priority ToDos by default
    if (!aData.CountValues(EPIMToDoPriority))
    {
        aEntry.SetPriorityL(EPIMToDoNativePriorityMedium);
    }
    // Calendar uses private synchronization by default
    if (!aData.CountValues(EPIMToDoClass))
    {
        aEntry.SetReplicationStatusL(CCalEntry::EPrivate);
    }
    // Calendar does not support timed ToDo so the time is set to 00:00 o'clock
    if (!aData.CountValues(EPIMToDoDue))
    {
        TTime thisTime;
        thisTime.HomeTime();
        // Set time to calendar specific due time. Currently this is the start
        // of the date. Note that No conversion needed since time is local
        TCalTime calThisTime;
        // Set time as local time since acquired above as local time
        calThisTime.SetTimeLocalL(StartOfDay(thisTime));
        aEntry.SetStartAndEndTimeL(calThisTime, calThisTime);
    }
    if (!aData.CountValues(EPIMToDoCompletionDate) && !aData.CountValues(
                EPIMToDoCompleted))
    {
        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
    }

}
// -----------------------------------------------------------------------------
// CPIMAgnToDoAdapter::ExportItemL
// (other items were commented in a header)
// -----------------------------------------------------------------------------
//
void CPIMAgnToDoAdapter::ExportItemL(const MPIMToDoItem& aItem,
                                     CCalEntry& aEntry, TBool aResetEntry)
{
    JELOG2(EPim);
    if (aResetEntry)
    {
        // Reset native entry for exporting new data
        aEntry.SetSummaryL(KNullDesC());
        aEntry.SetDescriptionL(KNullDesC());
        aEntry.SetPriorityL(0);
        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
    }

    // Export item data to the native ToDo calendar entry
    const MPIMItemData& itemData = aItem.ItemData();
    CArrayFix<TPIMField>* fields = itemData.FieldsLC();

    // Add default values to the calendar entry
    AddDefaultValuesToEntryL(itemData, aEntry);

    // Convert each field to the native ToDo calendar entry
    TInt count = fields->Count();
    for (TInt i = 0; i < count; i++)
    {
        TPIMToDoField field = static_cast<TPIMToDoField>(fields->At(i));
        ConvertToAgnL(field, aEntry, itemData);
    }
    CleanupStack::PopAndDestroy(fields);
}
// -----------------------------------------------------------------------------
// CPIMAgnToDoAdapter::ReadDateFieldsL
// (other items were commented in a header)
// -----------------------------------------------------------------------------
//
void CPIMAgnToDoAdapter::ReadDateFieldsL(MPIMItemData& aData, CCalEntry& aEntry)
{
    JELOG2(EPim);
    TTime nullTime = Time::NullTTime();
    // The Agenda todo entry end field is the due date
    TTime due(aEntry.EndTimeL().TimeLocalL());
    if (due != nullTime)
    {
        // Set due to the PIM API specific due date, in this case, the start of date
        // Note that PIM API uses times as UTC times so the due date must be in
        // correct format. Previously requested as local time -> do not change
        TPIMDate pimDueDate(StartOfDay(due));
        // Date must be converted UTC time because acquired as local above
        ConvertTimeL(pimDueDate, EPIMDateUTC);
        TPIMFieldData dueFieldData(EPIMToDoDue, KPIMAttrNone, pimDueDate);
        aData.AddValueL(dueFieldData);

        // Get alarm. Ownership is transferred to the caller. Alarm cannot be set
        // if the due date is not set because the calculation is done as an offset
        // from the ToDo due date.
        CCalAlarm* calAlarm = aEntry.AlarmL();
        if (calAlarm)
        {
            TTimeIntervalMinutes nativeValue = calAlarm->TimeOffset();
            // The alarm is not needed anymore so it can be deleted
            delete calAlarm;
            calAlarm = NULL;
            // Change the time to the start of the due date
            TTime startOfDayLocal(StartOfDay(due));
            // Calculate the difference from the start of due date and start time including
            // the original alarm offset which was previously read
            TTimeIntervalMinutes temp(0);
            User::LeaveIfError(startOfDayLocal.MinutesFrom(due, temp));
            // Since it is not possible to substract TTimeIntervalMinutes
            // from TTime (probably a Symbian error), the difference has
            // to be calculated using the following way...
            TInt alarm = (nativeValue.Int() + temp.Int()) * KPIMSecondsInMinute;
            // Add alarm value to the item
            TPIMFieldData fieldData(EPIMToDoExtAlarm, EPIMFieldInt,
                                    KPIMAttrNone, alarm);
            // Add value to the PIM item data
            aData.AddValueL(fieldData);
        }
    }

    // Completion date. If the item has a completion date, the item is then completed
    // and completed flag is set to true in PIM API. Null time if not crossed out.
    TTime completed = aEntry.CompletedTimeL().TimeUtcL();
    if (completed != nullTime)
    {
        TPIMFieldData dateData(EPIMToDoCompletionDate, KPIMAttrNone, completed);
        aData.AddValueL(dateData);
        // Note that boolean and integer fields must be identified in the constructor
        TPIMFieldData flag(EPIMToDoCompleted, EPIMFieldBoolean, KPIMAttrNone,
                           ETrue);
        aData.AddValueL(flag);
    }
}
// -----------------------------------------------------------------------------
// CPIMAgnToDoAdapter::ConvertDateToAgnL
// Makes date conversion from framework PIM item data field to To-do item field.
// -----------------------------------------------------------------------------
//
void CPIMAgnToDoAdapter::ConvertDateToAgnL(TPIMToDoField aField, // Date field to be converted
        TInt aIndex, // Index of the date field
        CCalEntry& aEntry, const MPIMItemData& aItem) // The PIM item to read the field from
{
    JELOG2(EPim);
    const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
    const TPIMDate& date = fieldData.DateValue();
    switch (aField)
    {
    case EPIMToDoDue:
    {
        // Because undated to-dos are possible, the due date can be set
        // to a null value.
        if (date != Time::NullTTime() && !IsDateInValidAgendaRange(date))
        {
            User::Leave(KErrAbort);
        }
        // Java dates cannot be set to native null TTime
        else
        {
            // Convert due date and time to calendar specific due time
            // Note that PIM API dates are in UTC time format -> convert
            TTime dueDate(date);
            ConvertTimeL(dueDate, EPIMDateLocal);
            // Set time to native entry. Note that the time is local
            TCalTime calDate;
            calDate.SetTimeLocalL(StartOfDay(dueDate));
            aEntry.SetStartAndEndTimeL(calDate, calDate);
        }
        break;
    }
    case EPIMToDoCompletionDate:
    {
        if (date != Time::NullTTime())
        {
            __ASSERT_ALWAYS(IsDateInValidAgendaRange(date), User::Leave(
                                KErrAbort));
            TCalTime calDate;
            calDate.SetTimeUtcL(date);
            aEntry.SetCompletedL(ETrue, calDate);
        }
        else
        {
            aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
        }
        break;
    }
    default:
    {
        __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
                                           EPIMPanicUnsupportedField));
    }
    }
}
// -----------------------------------------------------------------------------
// CPIMAgnToDoAdapter::ConvertBooleanToAgnL
// Makes boolean conversion from framework PIM item data field to To-do item field
// -----------------------------------------------------------------------------
//
void CPIMAgnToDoAdapter::ConvertBooleanToAgnL(TPIMToDoField aField, // Boolean field to be converted
        TInt aIndex, // Index of the date field
        CCalEntry& aEntry, // The Agenda model entry typecasted to a Todo item
        const MPIMItemData& aItem) // The PIM item to read the field from
{
    JELOG2(EPim);
    const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
    TBool booleanField = fieldData.BooleanValue();

    if (booleanField) // completed flag is set to value TRUE
    {
        // Check if the completed date field is present
        if (aItem.CountValues(EPIMToDoCompletionDate) == 0)
        {
            // If completed date is not present, use the current time.
            TTime currentTime;
            currentTime.HomeTime();
            TCalTime calCurrentTime;
            // Set time as local time since acquired above as local time
            calCurrentTime.SetTimeLocalL(currentTime);
            aEntry.SetCompletedL(ETrue, calCurrentTime);
        }
        else
        {
            TPIMFieldData completionData = aItem.ValueL(EPIMToDoCompletionDate,
                                           aIndex);
            const TPIMDate& date = completionData.DateValue();
            if (date != Time::NullTTime())
            {
                TCalTime calDate;
                calDate.SetTimeUtcL(date);
                aEntry.SetCompletedL(ETrue, calDate);
            }
            else
            {
                // If completed date is set to null time, use the current time.
                TTime currentTime;
                currentTime.HomeTime();
                TCalTime calCurrentTime;
                // Set time as local time since acquired above as local time
                calCurrentTime.SetTimeLocalL(currentTime);
                aEntry.SetCompletedL(ETrue, calCurrentTime);
            }
        }
    }
    else // completed flag is set to value FALSE
    {
        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
    }
}