/*
*******************************************************************************
* Copyright (C) 2007-2009, International Business Machines Corporation and    *
* others. All Rights Reserved.                                                *
*******************************************************************************
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

//#define DEBUG_RELDTFMT

#include <stdio.h>
#include <stdlib.h>

#include "reldtfmt.h"
#include "unicode/msgfmt.h"
#include "unicode/smpdtfmt.h"

#include "gregoimp.h" // for CalendarData
#include "cmemory.h"

U_NAMESPACE_BEGIN


/**
 * An array of URelativeString structs is used to store the resource data loaded out of the bundle.
 */
struct URelativeString {
    int32_t offset;         /** offset of this item, such as, the relative date **/
    int32_t len;            /** length of the string **/
    const UChar* string;    /** string, or NULL if not set **/
};

static const char DT_DateTimePatternsTag[]="DateTimePatterns";


UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RelativeDateFormat)

RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
DateFormat(other), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
fDateStyle(other.fDateStyle), fTimeStyle(other.fTimeStyle), fLocale(other.fLocale),
fDayMin(other.fDayMin), fDayMax(other.fDayMax),
fDatesLen(other.fDatesLen), fDates(NULL)
{
    if(other.fDateFormat != NULL) {
        fDateFormat = (DateFormat*)other.fDateFormat->clone();
    } else {
        fDateFormat = NULL;
    }
    if (fDatesLen > 0) {
        fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
        uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
    }
    //fCalendar = other.fCalendar->clone();
/*    
    if(other.fTimeFormat != NULL) {
        fTimeFormat = (DateFormat*)other.fTimeFormat->clone();
    } else {
        fTimeFormat = NULL;
    }
*/
}

RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const Locale& locale, UErrorCode& status)
 : DateFormat(), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
fDateStyle(dateStyle), fTimeStyle(timeStyle), fLocale(locale), fDatesLen(0), fDates(NULL)
 {
    if(U_FAILURE(status) ) {
        return;
    }
    
    if(fDateStyle != UDAT_NONE) {
        EStyle newStyle = (EStyle)(fDateStyle & ~UDAT_RELATIVE);
        // Create a DateFormat in the non-relative style requested.
        fDateFormat = createDateInstance(newStyle, locale);
    }
    if(fTimeStyle >= UDAT_FULL && fTimeStyle <= UDAT_SHORT) {
        fTimeFormat = createTimeInstance((EStyle)fTimeStyle, locale);
    } else if(fTimeStyle != UDAT_NONE) {
        // don't support other time styles (e.g. relative styles), for now
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return;
    }
    
    // Initialize the parent fCalendar, so that parse() works correctly.
    initializeCalendar(NULL, locale, status);
    loadDates(status);
}

RelativeDateFormat::~RelativeDateFormat() {
    delete fDateFormat;
    delete fTimeFormat;
    delete fCombinedFormat;
    uprv_free(fDates);
}


Format* RelativeDateFormat::clone(void) const {
    return new RelativeDateFormat(*this);
}

UBool RelativeDateFormat::operator==(const Format& other) const {
    if(DateFormat::operator==(other)) {
        // DateFormat::operator== guarantees following cast is safe
        RelativeDateFormat* that = (RelativeDateFormat*)&other;
        return (fDateStyle==that->fDateStyle   &&
                fTimeStyle==that->fTimeStyle   &&
                fLocale==that->fLocale);
    }
    return FALSE;
}

UnicodeString& RelativeDateFormat::format(  Calendar& cal,
                                UnicodeString& appendTo,
                                FieldPosition& pos) const {
                                
    UErrorCode status = U_ZERO_ERROR;
    UChar emptyStr = 0;
    UnicodeString dateString(&emptyStr);
    
    // calculate the difference, in days, between 'cal' and now.
    int dayDiff = dayDifference(cal, status);

    // look up string
    int32_t len = 0;
    const UChar *theString = getStringForDay(dayDiff, len, status);
    if(U_SUCCESS(status) && (theString!=NULL)) {
        // found a relative string
        dateString.setTo(theString, len);
    }
    
    if(fTimeFormat == NULL || fCombinedFormat == 0) {
        if (dateString.length() > 0) {
            appendTo.append(dateString);
        } else if(fDateFormat != NULL) {
            fDateFormat->format(cal,appendTo,pos);
        }
    } else {
        if (dateString.length() == 0 && fDateFormat != NULL) {
            fDateFormat->format(cal,dateString,pos);
        }
        UnicodeString timeString(&emptyStr);
        FieldPosition timepos = pos;
        fTimeFormat->format(cal,timeString,timepos);
        Formattable timeDateStrings[] = { timeString, dateString };
        fCombinedFormat->format(timeDateStrings, 2, appendTo, pos, status); // pos is ignored by this
        int32_t offset;
        if (pos.getEndIndex() > 0 && (offset = appendTo.indexOf(dateString)) >= 0) {
            // pos.field was found in dateString, offset start & end based on final position of dateString
            pos.setBeginIndex( pos.getBeginIndex() + offset );
            pos.setEndIndex( pos.getEndIndex() + offset );
        } else if (timepos.getEndIndex() > 0 && (offset = appendTo.indexOf(timeString)) >= 0) {
            // pos.field was found in timeString, offset start & end based on final position of timeString
            pos.setBeginIndex( timepos.getBeginIndex() + offset );
            pos.setEndIndex( timepos.getEndIndex() + offset );
        }
    }
    
    return appendTo;
}



UnicodeString&
RelativeDateFormat::format(const Formattable& obj, 
                         UnicodeString& appendTo, 
                         FieldPosition& pos,
                         UErrorCode& status) const
{
    // this is just here to get around the hiding problem
    // (the previous format() override would hide the version of
    // format() on DateFormat that this function correspond to, so we
    // have to redefine it here)
    return DateFormat::format(obj, appendTo, pos, status);
}


void RelativeDateFormat::parse( const UnicodeString& text,
                    Calendar& cal,
                    ParsePosition& pos) const {

    // Can the fDateFormat parse it?
    if(fDateFormat != NULL) {
        ParsePosition aPos(pos);
        fDateFormat->parse(text,cal,aPos);
        if((aPos.getIndex() != pos.getIndex()) && 
            (aPos.getErrorIndex()==-1)) {
                pos=aPos; // copy the sub parse
                return; // parsed subfmt OK
        }
    }
    
    // Linear search the relative strings
    for(int n=0;n<fDatesLen;n++) {
        if(fDates[n].string != NULL &&
            (0==text.compare(pos.getIndex(),
                         fDates[n].len,
                         fDates[n].string))) {
            UErrorCode status = U_ZERO_ERROR;
            
            // Set the calendar to now+offset
            cal.setTime(Calendar::getNow(),status);
            cal.add(UCAL_DATE,fDates[n].offset, status);
            
            if(U_FAILURE(status)) { 
                // failure in setting calendar fields
                pos.setErrorIndex(pos.getIndex()+fDates[n].len);
            } else {
                pos.setIndex(pos.getIndex()+fDates[n].len);
            }
            return;
        }
    }
    
    // parse failed
}

UDate
RelativeDateFormat::parse( const UnicodeString& text,
                         ParsePosition& pos) const {
    // redefined here because the other parse() function hides this function's
    // cunterpart on DateFormat
    return DateFormat::parse(text, pos);
}

UDate
RelativeDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
{
    // redefined here because the other parse() function hides this function's
    // counterpart on DateFormat
    return DateFormat::parse(text, status);
}


const UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErrorCode &status) const {
    if(U_FAILURE(status)) {
        return NULL;
    }
    
    // Is it outside the resource bundle's range?
    if(day < fDayMin || day > fDayMax) {
        return NULL; // don't have it.
    }
    
    // Linear search the held strings
    for(int n=0;n<fDatesLen;n++) {
        if(fDates[n].offset == day) {
            len = fDates[n].len;
            return fDates[n].string;
        }
    }
    
    return NULL;  // not found.
}

UnicodeString&
RelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
{
    if (!U_FAILURE(status)) {
        result.remove();
        if (fTimeFormat == NULL || fCombinedFormat == 0) {
            if (fDateFormat != NULL) {
                UnicodeString datePattern;
                this->toPatternDate(datePattern, status);
                if (!U_FAILURE(status)) {
                    result.setTo(datePattern);
                }
            }
        } else {
            UnicodeString datePattern, timePattern;
            this->toPatternDate(datePattern, status);
            this->toPatternTime(timePattern, status);
            if (!U_FAILURE(status)) {
                Formattable timeDatePatterns[] = { timePattern, datePattern };
                FieldPosition pos;
                fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
            }
        }
    }
    return result;
}

UnicodeString&
RelativeDateFormat::toPatternDate(UnicodeString& result, UErrorCode& status) const
{
    if (!U_FAILURE(status)) {
        result.remove();
        if ( fDateFormat ) {
            if ( fDateFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
                ((SimpleDateFormat*)fDateFormat)->toPattern(result);
            } else {
                status = U_UNSUPPORTED_ERROR;
            }
        }
    }
    return result;
}

UnicodeString&
RelativeDateFormat::toPatternTime(UnicodeString& result, UErrorCode& status) const
{
    if (!U_FAILURE(status)) {
        result.remove();
        if ( fTimeFormat ) {
            if ( fTimeFormat->getDynamicClassID()==SimpleDateFormat::getStaticClassID() ) {
                ((SimpleDateFormat*)fTimeFormat)->toPattern(result);
            } else {
                status = U_UNSUPPORTED_ERROR;
            }
        }
    }
    return result;
}

void
RelativeDateFormat::applyPatterns(const UnicodeString& datePattern, const UnicodeString& timePattern, UErrorCode &status)
{
    if (!U_FAILURE(status)) {
        if ( fDateFormat && fDateFormat->getDynamicClassID()!=SimpleDateFormat::getStaticClassID() ) {
            status = U_UNSUPPORTED_ERROR;
            return;
        }
        if ( fTimeFormat && fTimeFormat->getDynamicClassID()!=SimpleDateFormat::getStaticClassID() ) {
            status = U_UNSUPPORTED_ERROR;
            return;
        }
        if ( fDateFormat ) {
            ((SimpleDateFormat*)fDateFormat)->applyPattern(datePattern);
        }
        if ( fTimeFormat ) {
            ((SimpleDateFormat*)fTimeFormat)->applyPattern(timePattern);
        }
    }
}

void RelativeDateFormat::loadDates(UErrorCode &status) {
    CalendarData calData(fLocale, "gregorian", status);
    
    UErrorCode tempStatus = status;
    UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, tempStatus);
    if(U_SUCCESS(tempStatus)) {
        int32_t patternsSize = ures_getSize(dateTimePatterns);
        if (patternsSize > kDateTime) {
            int32_t resStrLen = 0;

            int32_t glueIndex = kDateTime;
            if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
                // Get proper date time format
                switch (fDateStyle) { 
 	            case kFullRelative: 
 	            case kFull: 
 	                glueIndex = kDateTimeOffset + kFull; 
 	                break; 
 	            case kLongRelative: 
 	            case kLong: 
 	                glueIndex = kDateTimeOffset + kLong; 
 	                break; 
 	            case kMediumRelative: 
 	            case kMedium: 
 	                glueIndex = kDateTimeOffset + kMedium; 
 	                break;         
 	            case kShortRelative: 
 	            case kShort: 
 	                glueIndex = kDateTimeOffset + kShort; 
 	                break; 
 	            default: 
 	                break; 
 	            } 
            }

            const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus);
            fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus);
        }
    }

    UResourceBundle *strings = calData.getByKey3("fields", "day", "relative", status);
    // set up min/max 
    fDayMin=-1;
    fDayMax=1;

    if(U_FAILURE(status)) {
        fDatesLen=0;
        return;
    }

    fDatesLen = ures_getSize(strings);
    fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);

    // Load in each item into the array...
    int n = 0;

    UResourceBundle *subString = NULL;
    
    while(ures_hasNext(strings) && U_SUCCESS(status)) {  // iterate over items
        subString = ures_getNextResource(strings, subString, &status);
        
        if(U_FAILURE(status) || (subString==NULL)) break;
        
        // key = offset #
        const char *key = ures_getKey(subString);
        
        // load the string and length
        int32_t aLen;
        const UChar* aString = ures_getString(subString, &aLen, &status);
        
        if(U_FAILURE(status) || aString == NULL) break;

        // calculate the offset
        int32_t offset = atoi(key);
        
        // set min/max
        if(offset < fDayMin) {
            fDayMin = offset;
        }
        if(offset > fDayMax) {
            fDayMax = offset;
        }
        
        // copy the string pointer
        fDates[n].offset = offset;
        fDates[n].string = aString;
        fDates[n].len = aLen; 

        n++;
    }
    ures_close(subString);
    
    // the fDates[] array could be sorted here, for direct access.
}


// this should to be in DateFormat, instead it was copied from SimpleDateFormat.

Calendar*
RelativeDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
{
    if(!U_FAILURE(status)) {
        fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
    }
    if (U_SUCCESS(status) && fCalendar == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
    }
    return fCalendar;
}

int32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
    if(U_FAILURE(status)) {
        return 0;
    }
    // TODO: Cache the nowCal to avoid heap allocs? Would be difficult, don't know the calendar type
    Calendar *nowCal = cal.clone();
    nowCal->setTime(Calendar::getNow(), status);

    // For the day difference, we are interested in the difference in the (modified) julian day number
    // which is midnight to midnight.  Using fieldDifference() is NOT correct here, because 
    // 6pm Jan 4th  to 10am Jan 5th should be considered "tomorrow".
    int32_t dayDiff = cal.get(UCAL_JULIAN_DAY, status) - nowCal->get(UCAL_JULIAN_DAY, status);

    delete nowCal;
    return dayDiff;
}

U_NAMESPACE_END

#endif

