/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: smlprstime.h,v 1.1.22.1 2004/07/09 01:57:56 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#ifndef SMLPRSTI_H
#define SMLPRSTI_H

enum SmilTimeType
{
    SmilTimeNone,
    SmilTimeOffset,
    SmilTimeClockValue,
    SmilTimeSyncBase,
#if defined(ENABLE_SYNC_TO_PREV)
    SmilTimeSyncToPrev,
#endif
    SmilTimeEvent,
    SmilTimeMediaMarker,
    SmilTimeWallclock
};

// Forward declarations
class CSmilElement;
class CHXString;

class SmilTimeValue
{
public:
    SmilTimeValue(IUnknown*     pContext,
                  UINT32        ulStartLine,
                  CSmilElement* pElement);
    virtual ~SmilTimeValue();

    HX_RESULT    parseValue(const char*          pPos,
                            SMILSyncAttributeTag nTag,
                            const char*          pThisElementID);
    INT32        setTimeOffset(time_t refTime);
    INT32        getTimeOffset() { return m_lOffset;}
    SmilTimeType getTimeType() { return m_type; }
    const char*  getEventName() { return (const char*) m_pEventName; }
    void         handleAsEvent(const char* pstr)
		 { if (pstr)
                     m_pEventName = (char*)pstr;
                     m_bTreatSyncArcAsEvent = TRUE;
		 }
    const char*  getIdRef() { return (const char*) m_idRef; }
    BOOL         isTimeResolved() { return m_bTimeIsResolved; }
    void         setIsTimeResolved(BOOL bIsResolved);
    HX_RESULT    getEffectiveResolvedTime(REF(INT32) lEffectiveResolvedTime);
    // /This sets the "base" time it resolved to, i.e., without the offset:
    void         setResolvedToTime(INT32 lWhen) { m_lResolvedToTime = lWhen; }
    INT32        getResolvedToTimeWithoutOffset() { return m_lResolvedToTime; }
    // /XXXEH- not sure yet whether we need these 2 functions:
    INT32        getWhenTimeWasResolved() { return m_lWhenTimeWasResolved; }
    void         setWhenTimeWasResolved(INT32 lWhen) { m_lWhenTimeWasResolved = lWhen; }
#if defined(ENABLE_SYNC_TO_PREV)
    BOOL         isSyncBaseTimeVal() { return (SmilTimeSyncBase   == m_type ||
                                               SmilTimeSyncToPrev == m_type); }
#else
    BOOL         isSyncBaseTimeVal() { return (SmilTimeSyncBase == m_type); }
#endif

    BOOL	 isResumeEvent() { return (m_type == SmilTimeEvent  &&  m_pEventName
			&&  0==strcmp(m_pEventName, "resumeEvent")); }
    BOOL	 isUndeferEvent() { return (m_type == SmilTimeEvent  &&  m_pEventName
			&&  0==strcmp(m_pEventName, "undeferEvent")); }
    HX_RESULT	 setPauseTime(LONG32 lTimeOfPause);
    ULONG32	 getPauseTime() { return m_lTimeOfPause;}

    BOOL         isSameTimeValue(SmilTimeValue* pOtherTimeVal);

    BOOL         deferUntil(LONG32 lNewStartTime);
    // Media-marker-related
    const char*  getFullMarkerName()         const { return m_pszMarkerName;             }
    BOOL         isExternalMarker()          const { return m_bIsExternalMarker;         }
    const char*  getExternalMarkerFileName() const { return m_pszExternalMarkerFileName; }
    const char*  getExternalMarkerName()     const { return m_pszExternalMarkerName;     }
    const char*  getMarkerName()             const { return (m_bIsExternalMarker     ?
                                                             m_pszExternalMarkerName :
                                                             m_pszMarkerName);           }
    void         setMarkerTime(UINT32 ulTime);
    // /Point back at "owner" of this:
    CSmilElement*      m_pElement;
    // /This is "foo" in the following example: "foo.beginEvent+5s"
    CHXString          m_idRef;
    // /This is id of element that deferred us:
    CHXString          m_awaitingThisOnesEndForUndefer;

    SMILEventSourceTag m_position;
    // /This is the '5' in: begin="foo.repeat(5)":
    UINT16             m_uRepeatIteration;
    SmilTimeType       m_type;
    // ONLY HX_BITFIELD MEMBERS SHOULD GO BELOW THIS LINE!
    // ALL OTHER MEMBER TYPES SHOULD GO ABOVE THIS LINE!
    HX_BITFIELD        m_bTreatSyncArcAsEvent : 1;
private:
    HX_RESULT parseOffset(const char* pCh);
    HX_RESULT parseClockValue(const char* pValue, UINT32& ulTimeValue);
#if defined(ENABLE_SYNC_TO_PREV)
    HX_RESULT parseSyncToPrev(REF(const char*) pPos);
#endif
    HX_RESULT parseWallClockValue(REF(const char*) pCh);
    HX_RESULT parseEvent(const char* pBase, const char* pEvent, const char* pOffset);
    HX_RESULT parseSyncBase(const char* pBase, const char* pEvent, const char* pOffset);
    HX_RESULT parseMarker(const char* pBase, const char* pEvent, const char* pOffset);

    IUnknown* m_pContext;
    UINT32    m_ulStartLine;
    // /This is the time offset from a sync-arc or event-arc, e.g.,
    // this is 5000 (milliseconds) in the following example:
    // "foo.beginEvent+5s":
    INT32     m_lOffset;
    // /Deferring and other things can change m_lOffset; this keeps track of
    // what it was set to originally in case we restart:
    INT32     m_lOriginalOffset;
    // the date defaults to -1/-1/-1 :==> today...
    INT16     m_year;
    INT8      m_month;
    INT8      m_day;
    // the time defaults to 00:00:00.0
    UINT8     m_hour;
    UINT8     m_min;
    UINT8     m_sec;
    UINT16    m_ms;
    // defaults to 0: local time
    INT16     m_UTCOffsetMin;
    // media-marker-related
    char*     m_pszMarkerName; // in begin="foo.marker()", this is what's inside the ()
    char*     m_pszExternalMarkerFileName; // in begin="foo.marker(foo.mmr#A)", this is "foo.mmr"
    char*     m_pszExternalMarkerName;     // in begin="foo.marker(foo.mmr#A)", this is "A"
    UINT32    m_ulMarkerTime;
    // /This is "beginEvent" in the following example: "foo.beginEvent+5s"
    char*     m_pEventName;
    // /This is the time that a non-clock/offset time resolved to; it differs
    // from m_lWhenTimeWasResolved in cases like pure sync-arc timing where
    // the resolved-to time is calculatable well in advance of the time it
    // was resolved:
    INT32     m_lResolvedToTime;
    // /This is the time passed in to CSmilParser::tryToResolveBeginEndEvents
    // which gets called whenever an event occurs.  We need this because
    // this tells us *when* we resolved and we want to keep this separate
    // from the m_lOffset in case it is negative, in which case our offset
    // is really m_lWhenTimeResolved with a clip-begin of m_lOffset:
    // /XXXEH- TODO: make sure final SMIL Boston spec agrees with above and
    // also, make sure that sync-arc and other time values that resolve after
    // the start of the presentation also get this set:
    INT32     m_lWhenTimeWasResolved;

    // /For resume event times, this keeps track of when *this was created so
    // we can recalculate the element's end time when a resume is needed:
    INT32     m_lTimeOfPause;
    // ONLY HX_BITFIELD MEMBERS SHOULD GO BELOW THIS LINE!
    // ALL OTHER MEMBER TYPES SHOULD GO ABOVE THIS LINE!
    HX_BITFIELD m_bRelativeToUTC : 1; // defaults to FALSE, relative to local time
    HX_BITFIELD m_bIsExternalMarker : 1;
    HX_BITFIELD m_bUsedToBeMediaMarker : 1;
    // /XXEH- TODO: make sure to reset this to FALSE whenever a repeat (or
    // seek?) happens:
    // /This says whether or not this's time is resolved to a clock val;
    HX_BITFIELD m_bTimeIsResolved : 1;
};

#endif
