// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2007-2012, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/

#include "utypeinfo.h"  // for 'typeid' to work

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/tzrule.h"
#include "unicode/tztrans.h"

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeZoneTransition)

TimeZoneTransition::TimeZoneTransition(UDate time, const TimeZoneRule& from, const TimeZoneRule& to)
: UObject(), fTime(time), fFrom(from.clone()), fTo(to.clone()) {
}

TimeZoneTransition::TimeZoneTransition()
: UObject(), fTime(0), fFrom(NULL), fTo(NULL) {
}

TimeZoneTransition::TimeZoneTransition(const TimeZoneTransition& source)
: UObject(), fTime(source.fTime), fFrom(NULL), fTo(NULL) {
      if (source.fFrom != NULL) {
          fFrom = source.fFrom->clone();
      }

      if (source.fTo != NULL) {
          fTo = source.fTo->clone();
      }
}

TimeZoneTransition::~TimeZoneTransition() {
    if (fFrom != NULL) {
        delete fFrom;
    }
    if (fTo != NULL) {
        delete fTo;
    }
}

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

TimeZoneTransition&
TimeZoneTransition::operator=(const TimeZoneTransition& right) {
    if (this != &right) {
        fTime = right.fTime;
        setFrom(*right.fFrom);
        setTo(*right.fTo);
    }
    return *this;
}

UBool
TimeZoneTransition::operator==(const TimeZoneTransition& that) const {
    if (this == &that) {
        return TRUE;
    }
    if (typeid(*this) != typeid(that)) {
        return FALSE;
    }
    if (fTime != that.fTime) {
        return FALSE;
    }
    if ((fFrom == NULL && that.fFrom == NULL)
        || (fFrom != NULL && that.fFrom != NULL && *fFrom == *(that.fFrom))) {
        if ((fTo == NULL && that.fTo == NULL)
            || (fTo != NULL && that.fTo != NULL && *fTo == *(that.fTo))) {
            return TRUE;
        }
    }
    return FALSE;
}

UBool
TimeZoneTransition::operator!=(const TimeZoneTransition& that) const {
    return !operator==(that);
}

void
TimeZoneTransition::setTime(UDate time) {
    fTime = time;
}

void
TimeZoneTransition::setFrom(const TimeZoneRule& from) {
    if (fFrom != NULL) {
        delete fFrom;
    }
    fFrom = from.clone();
}

void
TimeZoneTransition::adoptFrom(TimeZoneRule* from) {
    if (fFrom != NULL) {
        delete fFrom;
    }
    fFrom = from;
}

void
TimeZoneTransition::setTo(const TimeZoneRule& to) {
    if (fTo != NULL) {
        delete fTo;
    }
    fTo = to.clone();
}

void
TimeZoneTransition::adoptTo(TimeZoneRule* to) {
    if (fTo != NULL) {
        delete fTo;
    }
    fTo = to;
}

UDate
TimeZoneTransition::getTime(void) const {
    return fTime;
}

const TimeZoneRule*
TimeZoneTransition::getTo(void) const {
    return fTo;
}

const TimeZoneRule*
TimeZoneTransition::getFrom(void) const {
    return fFrom;
}

U_NAMESPACE_END

#endif

//eof
