/*
 * Copyright (C) 2008 Google (Roy Shea)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>
#include "winternl.h"
#include "mstask_private.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(mstask);

typedef struct
{
    ITaskTrigger ITaskTrigger_iface;
    LONG ref;
    TASK_TRIGGER triggerCond;
} TaskTriggerImpl;

static inline TaskTriggerImpl *impl_from_ITaskTrigger(ITaskTrigger *iface)
{
    return CONTAINING_RECORD(iface, TaskTriggerImpl, ITaskTrigger_iface);
}

static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface(
        ITaskTrigger* iface,
        REFIID riid,
        void **ppvObject)
{
    TaskTriggerImpl *This = impl_from_ITaskTrigger(iface);

    TRACE("IID: %s\n", debugstr_guid(riid));
    if (ppvObject == NULL)
        return E_POINTER;

    if (IsEqualGUID(riid, &IID_IUnknown) ||
            IsEqualGUID(riid, &IID_ITaskTrigger))
    {
        *ppvObject = &This->ITaskTrigger_iface;
        ITaskTrigger_AddRef(iface);
        return S_OK;
    }

    WARN("Unknown interface: %s\n", debugstr_guid(riid));
    *ppvObject = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI MSTASK_ITaskTrigger_AddRef(
        ITaskTrigger* iface)
{
    TaskTriggerImpl *This = impl_from_ITaskTrigger(iface);
    ULONG ref;
    TRACE("\n");
    ref = InterlockedIncrement(&This->ref);
    return ref;
}

static ULONG WINAPI MSTASK_ITaskTrigger_Release(
        ITaskTrigger* iface)
{
    TaskTriggerImpl *This = impl_from_ITaskTrigger(iface);
    ULONG ref;
    TRACE("\n");
    ref = InterlockedDecrement(&This->ref);
    if (ref == 0)
    {
        HeapFree(GetProcessHeap(), 0, This);
        InterlockedDecrement(&dll_ref);
    }
    return ref;
}

static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger(
        ITaskTrigger* iface,
        const PTASK_TRIGGER pTrigger)
{
    TaskTriggerImpl * This = impl_from_ITaskTrigger(iface);
    TIME_FIELDS field_time;
    LARGE_INTEGER sys_time;
    TASK_TRIGGER tmp_trigger_cond;

    TRACE("(%p, %p)\n", iface, pTrigger);

    /* Verify valid structure size */
    if (pTrigger->cbTriggerSize != sizeof(*pTrigger))
        return E_INVALIDARG;
    tmp_trigger_cond.cbTriggerSize = pTrigger->cbTriggerSize;

    /* Reserved field must be zero */
    tmp_trigger_cond.Reserved1 = 0;

    /* Verify and set valid start date and time */
    memset(&field_time, 0, sizeof(field_time));
    field_time.Year = pTrigger->wBeginYear;
    field_time.Month = pTrigger->wBeginMonth;
    field_time.Day = pTrigger->wBeginDay;
    field_time.Hour = pTrigger->wStartHour;
    field_time.Minute = pTrigger->wStartMinute;
    if (!RtlTimeFieldsToTime(&field_time, &sys_time))
        return E_INVALIDARG;
    tmp_trigger_cond.wBeginYear = pTrigger->wBeginYear;
    tmp_trigger_cond.wBeginMonth = pTrigger->wBeginMonth;
    tmp_trigger_cond.wBeginDay = pTrigger->wBeginDay;
    tmp_trigger_cond.wStartHour = pTrigger->wStartHour;
    tmp_trigger_cond.wStartMinute = pTrigger->wStartMinute;

    /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */
    if (pTrigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE)
    {
        memset(&field_time, 0, sizeof(field_time));
        field_time.Year = pTrigger->wEndYear;
        field_time.Month = pTrigger->wEndMonth;
        field_time.Day = pTrigger->wEndDay;
        if (!RtlTimeFieldsToTime(&field_time, &sys_time))
            return E_INVALIDARG;
    }

    /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */
    tmp_trigger_cond.wEndYear = pTrigger->wEndYear;
    tmp_trigger_cond.wEndMonth = pTrigger->wEndMonth;
    tmp_trigger_cond.wEndDay = pTrigger->wEndDay;

    /* Verify duration and interval pair */
    if (pTrigger->MinutesDuration <= pTrigger->MinutesInterval &&
            pTrigger->MinutesInterval > 0)
        return E_INVALIDARG;
    tmp_trigger_cond.MinutesDuration = pTrigger->MinutesDuration;
    tmp_trigger_cond.MinutesInterval = pTrigger->MinutesInterval;

    /* Copy over flags */
    tmp_trigger_cond.rgFlags = pTrigger->rgFlags;

    /* Set TriggerType dependent fields of Type union */
    tmp_trigger_cond.TriggerType = pTrigger->TriggerType;
    switch (pTrigger->TriggerType)
    {
        case TASK_TIME_TRIGGER_DAILY:
            tmp_trigger_cond.Type.Daily.DaysInterval =
                    pTrigger->Type.Daily.DaysInterval;
            break;
        case TASK_TIME_TRIGGER_WEEKLY:
            tmp_trigger_cond.Type.Weekly.WeeksInterval =
                    pTrigger->Type.Weekly.WeeksInterval;
            tmp_trigger_cond.Type.Weekly.rgfDaysOfTheWeek =
                    pTrigger->Type.Weekly.rgfDaysOfTheWeek;
            break;
        case TASK_TIME_TRIGGER_MONTHLYDATE:
            tmp_trigger_cond.Type.MonthlyDate.rgfDays =
                    pTrigger->Type.MonthlyDate.rgfDays;
            tmp_trigger_cond.Type.MonthlyDate.rgfMonths =
                    pTrigger->Type.MonthlyDate.rgfMonths;
            break;
        case TASK_TIME_TRIGGER_MONTHLYDOW:
            tmp_trigger_cond.Type.MonthlyDOW.wWhichWeek =
                    pTrigger->Type.MonthlyDOW.wWhichWeek;
            tmp_trigger_cond.Type.MonthlyDOW.rgfDaysOfTheWeek =
                    pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek;
            tmp_trigger_cond.Type.MonthlyDOW.rgfMonths =
                    pTrigger->Type.MonthlyDOW.rgfMonths;
            break;
        case TASK_TIME_TRIGGER_ONCE:
        case TASK_EVENT_TRIGGER_ON_IDLE:
        case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
        case TASK_EVENT_TRIGGER_AT_LOGON:
        default:
            tmp_trigger_cond.Type = This->triggerCond.Type;
            break;
    }

    /* Reserved field must be zero */
    tmp_trigger_cond.Reserved2 = 0;

    /* wRandomMinutesInterval not currently used and is initialized to zero */
    tmp_trigger_cond.wRandomMinutesInterval = 0;

    /* Update object copy of triggerCond */
    This->triggerCond = tmp_trigger_cond;

    return S_OK;
}

static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger(
        ITaskTrigger* iface,
        PTASK_TRIGGER pTrigger)
{
    TaskTriggerImpl * This = impl_from_ITaskTrigger(iface);

    TRACE("(%p, %p)\n", iface, pTrigger);

    /* Native implementation doesn't verify equivalent cbTriggerSize fields */

    /* Copy relevant fields of the structure */
    pTrigger->cbTriggerSize = This->triggerCond.cbTriggerSize;
    pTrigger->Reserved1 = 0;
    pTrigger->wBeginYear = This->triggerCond.wBeginYear;
    pTrigger->wBeginMonth = This->triggerCond.wBeginMonth;
    pTrigger->wBeginDay = This->triggerCond.wBeginDay;
    pTrigger->wEndYear = This->triggerCond.wEndYear;
    pTrigger->wEndMonth = This->triggerCond.wEndMonth;
    pTrigger->wEndDay = This->triggerCond.wEndDay;
    pTrigger->wStartHour = This->triggerCond.wStartHour;
    pTrigger->wStartMinute = This->triggerCond.wStartMinute;
    pTrigger->MinutesDuration = This->triggerCond.MinutesDuration;
    pTrigger->MinutesInterval = This->triggerCond.MinutesInterval;
    pTrigger->rgFlags = This->triggerCond.rgFlags;
    pTrigger->TriggerType = This->triggerCond.TriggerType;
    switch (This->triggerCond.TriggerType)
    {
        case TASK_TIME_TRIGGER_DAILY:
            pTrigger->Type.Daily.DaysInterval =
                    This->triggerCond.Type.Daily.DaysInterval;
            break;
        case TASK_TIME_TRIGGER_WEEKLY:
            pTrigger->Type.Weekly.WeeksInterval =
                    This->triggerCond.Type.Weekly.WeeksInterval;
            pTrigger->Type.Weekly.rgfDaysOfTheWeek =
                    This->triggerCond.Type.Weekly.rgfDaysOfTheWeek;
            break;
        case TASK_TIME_TRIGGER_MONTHLYDATE:
            pTrigger->Type.MonthlyDate.rgfDays =
                    This->triggerCond.Type.MonthlyDate.rgfDays;
            pTrigger->Type.MonthlyDate.rgfMonths =
                    This->triggerCond.Type.MonthlyDate.rgfMonths;
            break;
        case TASK_TIME_TRIGGER_MONTHLYDOW:
            pTrigger->Type.MonthlyDOW.wWhichWeek =
                    This->triggerCond.Type.MonthlyDOW.wWhichWeek;
            pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek =
                    This->triggerCond.Type.MonthlyDOW.rgfDaysOfTheWeek;
            pTrigger->Type.MonthlyDOW.rgfMonths =
                    This->triggerCond.Type.MonthlyDOW.rgfMonths;
            break;
        case TASK_TIME_TRIGGER_ONCE:
        case TASK_EVENT_TRIGGER_ON_IDLE:
        case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
        case TASK_EVENT_TRIGGER_AT_LOGON:
        default:
            break;
    }
    pTrigger->Reserved2 = 0;
    pTrigger->wRandomMinutesInterval = 0;
    return S_OK;
}

static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString(
        ITaskTrigger* iface,
        LPWSTR *ppwszTrigger)
{
    FIXME("Not implemented\n");
    return E_NOTIMPL;
}

static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl =
{
    MSTASK_ITaskTrigger_QueryInterface,
    MSTASK_ITaskTrigger_AddRef,
    MSTASK_ITaskTrigger_Release,
    MSTASK_ITaskTrigger_SetTrigger,
    MSTASK_ITaskTrigger_GetTrigger,
    MSTASK_ITaskTrigger_GetTriggerString
};

HRESULT TaskTriggerConstructor(LPVOID *ppObj)
{
    TaskTriggerImpl *This;
    SYSTEMTIME time;
    TRACE("(%p)\n", ppObj);

    This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
    if (!This)
        return E_OUTOFMEMORY;

    This->ITaskTrigger_iface.lpVtbl = &MSTASK_ITaskTriggerVtbl;
    This->ref = 1;

    /* Most fields of triggerCond default to zero.  Initialize other
     * fields to default values. */
    memset(&This->triggerCond, 0, sizeof(TASK_TRIGGER));
    GetLocalTime(&time);
    This->triggerCond.cbTriggerSize = sizeof(This->triggerCond);
    This->triggerCond.wBeginYear = time.wYear;
    This->triggerCond.wBeginMonth = time.wMonth;
    This->triggerCond.wBeginDay = time.wDay;
    This->triggerCond.wStartHour = time.wHour;
    This->triggerCond.wStartMinute = time.wMinute;
    This->triggerCond.rgFlags = TASK_TRIGGER_FLAG_DISABLED;
    This->triggerCond.TriggerType = TASK_TIME_TRIGGER_DAILY,
    This->triggerCond.Type.Daily.DaysInterval = 1;

    *ppObj = &This->ITaskTrigger_iface;
    InterlockedIncrement(&dll_ref);
    return S_OK;
}
