"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScopedDateTimePropertyDefinition = void 0;
const DateTime_1 = require("../DateTime");
const EwsLogging_1 = require("../Core/EwsLogging");
const EwsUtilities_1 = require("../Core/EwsUtilities");
const ExchangeVersion_1 = require("../Enumerations/ExchangeVersion");
const PropertyException_1 = require("../Exceptions/PropertyException");
const ExtensionMethods_1 = require("../ExtensionMethods");
const Strings_1 = require("../Strings");
const TimeZoneInfo_1 = require("../TimeZoneInfo");
const DateTimePropertyDefinition_1 = require("./DateTimePropertyDefinition");
/**
 * @internal Represents a property definition for DateTime values scoped to a specific time zone property.
 */
class ScopedDateTimePropertyDefinition extends DateTimePropertyDefinition_1.DateTimePropertyDefinition {
    /**
     * @internal Initializes a new instance of the **ScopedDateTimePropertyDefinition** class.
     *
     * @param   {string}                            propertyName                    Name of the property.
     * @param   {string}                            xmlElementName                  Name of the XML element.
     * @param   {ExchangeVersion}                   version                         The version.
     * @param   {string}                            uri                             The URI.
     * @param   {PropertyDefinitionFlags}           flags                           The flags.
     * @param   {GetPropertyDefinitionCallback}     getPropertyDefinitionCallback   The callback that will be used to retrieve the time zone property.
     */
    constructor(propertyName, xmlElementName, uri, flags, version, getPropertyDefinitionCallback) {
        super(propertyName, xmlElementName, uri, flags, version);
        EwsLogging_1.EwsLogging.Assert(getPropertyDefinitionCallback != null, "ScopedDateTimePropertyDefinition.ctor", "getPropertyDefinitionCallback is null.");
        this.getPropertyDefinitionCallback = getPropertyDefinitionCallback;
    }
    /**
     * Gets the time zone property to which to scope times.
     *
     * @param   {ExchangeVersion}   version   The EWS version for which the property is to be retrieved.
     * @return  {PropertyDefinition}             The PropertyDefinition of the scoping time zone property.
     */
    GetTimeZoneProperty(version) {
        var timeZoneProperty = this.getPropertyDefinitionCallback(version);
        EwsLogging_1.EwsLogging.Assert(timeZoneProperty != null, "ScopedDateTimePropertyDefinition.GetTimeZoneProperty", "timeZoneProperty is null.");
        return timeZoneProperty;
    }
    /**
     * @internal Scopes the date time property to the appropriate time zone, if necessary.
     *
     * @param   {ExchangeServiceBase}   service             The service emitting the request.
     * @param   {DateTime}              dateTime            The date time.
     * @param   {PropertyBag}           propertyBag         The property bag.
     * @param   {boolean}               isUpdateOperation   Indicates whether the scoping is to be performed in the context of an update operation.
     * @return  {DateTime}              The converted DateTime.
     */
    ScopeToTimeZone(service, dateTime, propertyBag, isUpdateOperation) {
        EwsLogging_1.EwsLogging.DebugLog("[ScopedDateTimePropertyDefinition.ScopeToTimeZone]: TimeZone info has been updated, Please report any bugs to github");
        if (!propertyBag.Owner.GetIsCustomDateTimeScopingRequired()) {
            // Most item types do not require a custom scoping mechanism. For those item types,
            // use the default scoping mechanism.
            return super.ScopeToTimeZone(service, dateTime, propertyBag, isUpdateOperation);
        }
        else {
            // Appointment, however, requires a custom scoping mechanism which is based on an
            // associated time zone property.
            var timeZoneProperty = this.GetTimeZoneProperty(service.RequestedServerVersion);
            var timeZonePropertyValue = { outValue: null };
            var timeZonePropertyIsSet = propertyBag.TryGetProperty(timeZoneProperty, timeZonePropertyValue);
            if (timeZonePropertyValue.outValue != null && propertyBag.IsPropertyUpdated(timeZoneProperty)) {
                // If we have the associated time zone property handy and if it has been updated locally,
                // then we scope the date time to that time zone.
                try {
                    var convertedDateTime = EwsUtilities_1.EwsUtilities.ConvertTime(dateTime, timeZonePropertyValue.outValue, TimeZoneInfo_1.TimeZoneInfo.Utc);
                    // This is necessary to stamp the date/time with the Local kind.
                    return new DateTime_1.DateTime(convertedDateTime.TotalMilliSeconds, DateTime_1.DateTimeKind.Utc);
                }
                catch (e) {
                    throw new PropertyException_1.PropertyException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.InvalidDateTime, dateTime), this.Name, e);
                }
            }
            else {
                if (isUpdateOperation) {
                    // In an update operation, what we do depends on what version of EWS
                    // we are targeting.
                    if (service.RequestedServerVersion == ExchangeVersion_1.ExchangeVersion.Exchange2007_SP1) {
                        // For Exchange 2007 SP1, we still need to scope to the service's time zone.
                        return super.ScopeToTimeZone(service, dateTime, propertyBag, isUpdateOperation);
                    }
                    else {
                        // Otherwise, we let the server scope to the appropriate time zone.
                        return dateTime;
                    }
                }
                else {
                    // In a Create operation, always scope to the service's time zone.
                    return super.ScopeToTimeZone(service, dateTime, propertyBag, isUpdateOperation);
                }
            }
        }
    }
}
exports.ScopedDateTimePropertyDefinition = ScopedDateTimePropertyDefinition;
//# sourceMappingURL=ScopedDateTimePropertyDefinition.js.map