"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RelationalFilter = void 0;
const PropertyDefinitionBase_1 = require("../../PropertyDefinitions/PropertyDefinitionBase");
const ServiceValidationException_1 = require("../../Exceptions/ServiceValidationException");
const ExtensionMethods_1 = require("../../ExtensionMethods");
const Strings_1 = require("../../Strings");
const XmlAttributeNames_1 = require("../../Core/XmlAttributeNames");
const XmlElementNames_1 = require("../../Core/XmlElementNames");
const XmlNamespace_1 = require("../../Enumerations/XmlNamespace");
const SearchFilter_PropertyBasedFilter_1 = require("./SearchFilter.PropertyBasedFilter");
/**
 * Represents the base class for relational filters (for example, IsEqualTo, IsGreaterThan or IsLessThanOrEqualTo).
 */
class RelationalFilter extends SearchFilter_PropertyBasedFilter_1.PropertyBasedFilter {
    constructor(propertyDefinition = null, otherPropertyDefinitionOrValue = null) {
        arguments.length === 0 ? super() : super(propertyDefinition);
        if (arguments.length === 0) {
            return;
        }
        if (otherPropertyDefinitionOrValue instanceof PropertyDefinitionBase_1.PropertyDefinitionBase) {
            this.otherPropertyDefinition = otherPropertyDefinitionOrValue;
        }
        else {
            this.value = otherPropertyDefinitionOrValue;
        }
    }
    /**
     * Gets or sets the definition of the property to compare with. Property definitions are available as static members from schema classes (for example, EmailMessageSchema.Subject, AppointmentSchema.Start, ContactSchema.GivenName, etc.)
     * The OtherPropertyDefinition and Value properties are mutually exclusive; setting one resets the other to null.
     */
    get OtherPropertyDefinition() {
        return this.otherPropertyDefinition;
    }
    set OtherPropertyDefinition(value) {
        this.SetFieldValue({ getValue: () => this.otherPropertyDefinition, setValue: (updateValue) => { this.otherPropertyDefinition = updateValue; } }, value);
        this.value = null;
    }
    /**
     * Gets or sets the value to compare with. The Value and OtherPropertyDefinition properties are mutually exclusive; setting one resets the other to null.
     */
    get Value() {
        return this.value;
    }
    set Value(value) {
        this.SetFieldValue({ getValue: () => this.value, setValue: (updateValue) => { this.value = updateValue; } }, value);
        this.otherPropertyDefinition = null;
    }
    /**
     * @internal Validate instance.
     */
    InternalValidate() {
        super.InternalValidate();
        if (this.otherPropertyDefinition == null && this.value == null) {
            throw new ServiceValidationException_1.ServiceValidationException(Strings_1.Strings.EqualityComparisonFilterIsInvalid);
        }
        else if (this.value != null) {
            // All common value types (String, Int32, DateTime, ...) implement IConvertible.
            // Value types that don't implement IConvertible must implement ISearchStringProvider 
            // in order to be used in a search filter.
            if (!(ExtensionMethods_1.TypeSystem.IsGenericType(this.value) || (typeof this.value.GetSearchString === 'function'))) // checking - ISearchStringProvider
             {
                throw new ServiceValidationException_1.ServiceValidationException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.SearchFilterComparisonValueTypeIsNotSupported, this.constructor.name));
            }
        }
    }
    /**
     * @internal Loads service object from XML.
     *
     * @param   {any}				jsObject	Json Object converted from XML.
     * @param   {ExchangeService}	service	The service.
     */
    LoadFromXmlJsObject(jsObject, service) {
        super.LoadFromXmlJsObject(jsObject, service);
        let jsonFieldUriOrConstant = jsObject[XmlElementNames_1.XmlElementNames.FieldURIOrConstant];
        if (ExtensionMethods_1.TypeSystem.GetJsObjectTypeName(jsonFieldUriOrConstant) == XmlElementNames_1.XmlElementNames.Constant) {
            this.value = jsonFieldUriOrConstant[XmlElementNames_1.XmlElementNames.Value];
        }
        else {
            this.otherPropertyDefinition = PropertyDefinitionBase_1.PropertyDefinitionBase.LoadFromXmlJsObject(jsObject);
        }
    }
    /**
     * @internal Writes the elements to XML.
     *
     * @param   {EwsServiceXmlWriter}   writer   The writer.
     */
    WriteElementsToXml(writer) {
        super.WriteElementsToXml(writer);
        writer.WriteStartElement(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.FieldURIOrConstant);
        if (this.Value != null) {
            writer.WriteStartElement(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.Constant);
            writer.WriteAttributeValue(XmlAttributeNames_1.XmlAttributeNames.Value, true /* alwaysWriteEmptyString */, this.Value);
            writer.WriteEndElement(); // Constant
        }
        else {
            this.OtherPropertyDefinition.WriteToXml(writer);
        }
        writer.WriteEndElement(); // FieldURIOrConstant
    }
}
exports.RelationalFilter = RelationalFilter;
//# sourceMappingURL=SearchFilter.RelationalFilter.js.map