"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PropertySet = void 0;
const ExtensionMethods_1 = require("../ExtensionMethods");
const BasePropertySet_1 = require("../Enumerations/BasePropertySet");
const BodyType_1 = require("../Enumerations/BodyType");
const AltDictionary_1 = require("../AltDictionary");
const EwsLogging_1 = require("../Core/EwsLogging");
const EwsUtilities_1 = require("./EwsUtilities");
const ExchangeVersion_1 = require("../Enumerations/ExchangeVersion");
const LazyMember_1 = require("./LazyMember");
const PropertyDefinition_1 = require("../PropertyDefinitions/PropertyDefinition");
const PropertyDefinitionFlags_1 = require("../Enumerations/PropertyDefinitionFlags");
const ServiceObjectType_1 = require("../Enumerations/ServiceObjectType");
const ServiceValidationException_1 = require("../Exceptions/ServiceValidationException");
const ServiceVersionException_1 = require("../Exceptions/ServiceVersionException");
const Strings_1 = require("../Strings");
const XmlElementNames_1 = require("../Core/XmlElementNames");
const XmlNamespace_1 = require("../Enumerations/XmlNamespace");
/**
 * Represents a set of item or folder properties. Property sets are used to indicate what properties of an item or folder should be loaded when binding to an existing item or folder or when loading an item or folder's properties.
 *
 * @sealed
 */
class PropertySet {
    constructor(basePropertySetOrAdditionalProperties = null, _additionalProperties = null) {
        /**
         * The base property set this property set is based upon.
         */
        this.basePropertySet = BasePropertySet_1.BasePropertySet.IdOnly;
        /**
         * The list of additional properties included in this property set.
         */
        this.additionalProperties = [];
        /**
         * The requested body type for get and find operations. If null, the "best body" is returned.
         */
        this.requestedBodyType = null; //nullable
        /**
         * The requested unique body type for get and find operations. If null, the should return the same value as body type.
         */
        this.requestedUniqueBodyType = null; //nullable
        /**
         * The requested normalized body type for get and find operations. If null, the should return the same value as body type.
         */
        this.requestedNormalizedBodyType = null; //nullable
        /**
         * Value indicating whether or not the server should filter HTML content.
         */
        this.filterHtml = null; //nullable
        /**
         * Value indicating whether or not the server should convert HTML code page to UTF8.
         */
        this.convertHtmlCodePageToUTF8 = null; //nullable
        /**
         * Value of the URL template to use for the src attribute of inline IMG elements.
         */
        this.inlineImageUrlTemplate = null;
        /**
         * Value indicating whether or not the server should block references to external images.
         */
        this.blockExternalImages = null; //nullable
        /**
         * Value indicating whether or not to add a blank target attribute to anchor links.
         */
        this.addTargetToLinks = null; //nullable
        /**
         * Value indicating whether or not this PropertySet can be modified.
         */
        this.isReadOnly = false;
        /**
         * Value indicating the maximum body size to retrieve.
         */
        this.maximumBodySize = null; //nullable
        let argsLength = arguments.length;
        let basePropertySet = BasePropertySet_1.BasePropertySet.IdOnly;
        let additionalProperties = [];
        if (argsLength >= 1) {
            if (typeof basePropertySetOrAdditionalProperties === 'number') {
                basePropertySet = basePropertySetOrAdditionalProperties;
            }
            else if (ExtensionMethods_1.ArrayHelper.isArray(basePropertySetOrAdditionalProperties)) {
                additionalProperties = basePropertySetOrAdditionalProperties;
            }
            else {
                additionalProperties = [basePropertySetOrAdditionalProperties];
            }
        }
        if (argsLength >= 2) {
            if (ExtensionMethods_1.ArrayHelper.isArray(_additionalProperties)) {
                additionalProperties = _additionalProperties;
            }
            else {
                additionalProperties.push(_additionalProperties);
            }
        }
        if (argsLength > 2) {
            for (var _i = 2; _i < arguments.length; _i++) {
                additionalProperties.push(arguments[_i]);
            }
        }
        this.basePropertySet = basePropertySet;
        if (additionalProperties.length > 0) {
            this.additionalProperties = additionalProperties;
            //ArrayHelper.AddRange(this.additionalProperties, <any>additionalProperties);
            //this.additionalProperties.push.apply(this.additionalProperties, additionalProperties); //todo: addrange for array - http://typescript.codeplex.com/workitem/1422
        }
    }
    /**
     * @internal Maps BasePropertySet values to EWS's BaseShape values.
     */
    static get DefaultPropertySetMap() {
        return this.defaultPropertySetMap;
    }
    /**
     * Gets or sets the base property set the property set is based upon.
     */
    get BasePropertySet() {
        return this.basePropertySet;
    }
    set BasePropertySet(value) {
        this.ThrowIfReadonly();
        this.basePropertySet = value;
    }
    /**
     * Gets or sets type of body that should be loaded on items. If RequestedBodyType is null, body is returned as HTML if available, plain text otherwise.
     *
     * @Nullable
     */
    get RequestedBodyType() {
        return this.requestedBodyType;
    }
    set RequestedBodyType(value) {
        this.ThrowIfReadonly();
        this.requestedBodyType = value;
    }
    /**
     * Gets or sets type of body that should be loaded on items. If null, the should return the same value as body type.
     *
     * @nullable
     */
    get RequestedUniqueBodyType() {
        return this.requestedUniqueBodyType;
    }
    set RequestedUniqueBodyType(value) {
        this.ThrowIfReadonly();
        this.requestedUniqueBodyType = value;
    }
    /**
     * Gets or sets type of normalized body that should be loaded on items. If null, the should return the same value as body type.
     *
     * @nullable
     */
    get RequestedNormalizedBodyType() {
        return this.requestedNormalizedBodyType;
    }
    set RequestedNormalizedBodyType(value) {
        this.ThrowIfReadonly();
        this.requestedNormalizedBodyType = value;
    }
    /**
     * Gets the number of explicitly added properties in this set.
     */
    get Count() {
        return this.additionalProperties.length;
    }
    /**
     * Gets or sets value indicating whether or not to filter potentially unsafe HTML content from message bodies.
     *
     * @nullable
     */
    get FilterHtmlContent() {
        return this.filterHtml;
    }
    set FilterHtmlContent(value) {
        this.ThrowIfReadonly();
        this.filterHtml = value;
    }
    /**
     * Gets or sets value indicating whether or not to convert HTML code page to UTF8 encoding.
     *
     * @nullable
     */
    get ConvertHtmlCodePageToUTF8() {
        return this.convertHtmlCodePageToUTF8;
    }
    set ConvertHtmlCodePageToUTF8(value) {
        this.ThrowIfReadonly();
        this.convertHtmlCodePageToUTF8 = value;
    }
    /**
     * Gets or sets a value of the URL template to use for the src attribute of inline IMG elements.
     *
     * @nullable
     */
    get InlineImageUrlTemplate() {
        return this.inlineImageUrlTemplate;
    }
    set InlineImageUrlTemplate(value) {
        this.ThrowIfReadonly();
        this.inlineImageUrlTemplate = value;
    }
    /**
     * Gets or sets value indicating whether or not to convert inline images to data URLs.
     *
     * @nullable
     */
    get BlockExternalImages() {
        return this.blockExternalImages;
    }
    set BlockExternalImages(value) {
        this.ThrowIfReadonly();
        this.blockExternalImages = value;
    }
    /**
     * Gets or sets value indicating whether or not to add blank target attribute to anchor links.
     *
     * @nullable
     */
    get AddBlankTargetToLinks() {
        return this.addTargetToLinks;
    }
    set AddBlankTargetToLinks(value) {
        this.ThrowIfReadonly();
        this.addTargetToLinks = value;
    }
    /**
     * Gets or sets the maximum size of the body to be retrieved.
     *
     * @nullable
     *
     * @value   The maximum size of the body to be retrieved.
     */
    get MaximumBodySize() {
        return this.maximumBodySize;
    }
    set MaximumBodySize(value) {
        this.ThrowIfReadonly();
        this.maximumBodySize = value;
    }
    /**
     * Gets the **PropertyDefinitionBase** at the specified index. this[int] indexer
     *
     * @param   {number}   index   Index.
     */
    _getItem(index) {
        return this.additionalProperties[index];
    }
    /**
     * Adds the specified property to the property set.
     *
     * @param   {PropertyDefinitionBase}   property   The property to add.
     */
    Add(property) {
        this.ThrowIfReadonly();
        EwsUtilities_1.EwsUtilities.ValidateParam(property, "property");
        if (this.additionalProperties.indexOf(property) === -1) {
            this.additionalProperties.push(property);
        }
    }
    /**
     * Adds the specified properties to the property set.
     *
     * @param   {PropertyDefinitionBase[]}   properties   The properties to add.
     */
    AddRange(properties) {
        this.ThrowIfReadonly();
        EwsUtilities_1.EwsUtilities.ValidateParamCollection(properties, "properties");
        for (let property of properties) {
            this.Add(property);
        }
    }
    /**
     * Remove all explicitly added properties from the property set.
     */
    Clear() {
        this.ThrowIfReadonly();
        this.additionalProperties.splice(0);
    }
    /**
     * Determines whether the specified property has been explicitly added to this property set using the Add or AddRange methods.
     *
     * @param   {PropertyDefinitionBase}    property   The property.
     * @return  {boolean}                   true if this property set contains the specified propert]; otherwise, false.
     */
    Contains(property) { return this.additionalProperties.indexOf(property) !== -1; }
    /**
     * Creates a read-only PropertySet.
     *
     * @param   {BasePropertySet}   basePropertySet   The base property set.
     * @return  {PropertySet}       PropertySet
     */
    static CreateReadonlyPropertySet(basePropertySet) {
        let propertySet = new PropertySet(basePropertySet);
        propertySet.isReadOnly = true;
        return propertySet;
    }
    /**
     *  Returns an enumerator that iterates through the collection. this case this.additionalProperties itself
     */
    GetEnumerator() {
        return this.additionalProperties;
    }
    /**
     * Gets the name of the shape.
     *
     * @param   {ServiceObjectType}     serviceObjectType   Type of the service object.
     * @return  {string}                Shape name.
     */
    static GetShapeName(serviceObjectType) {
        switch (serviceObjectType) {
            case ServiceObjectType_1.ServiceObjectType.Item:
                return XmlElementNames_1.XmlElementNames.ItemShape;
            case ServiceObjectType_1.ServiceObjectType.Folder:
                return XmlElementNames_1.XmlElementNames.FolderShape;
            case ServiceObjectType_1.ServiceObjectType.Conversation:
                return XmlElementNames_1.XmlElementNames.ConversationShape;
            default:
                EwsLogging_1.EwsLogging.Assert(false, "PropertySet.GetShapeName", ExtensionMethods_1.StringHelper.Format("An unexpected object type {0} for property shape. This code path should never be reached.", serviceObjectType));
                return ExtensionMethods_1.StringHelper.Empty;
        }
    }
    /**
     * @internal Validates this property set.
     */
    InternalValidate() {
        for (let i = 0; i < this.additionalProperties.length; i++) {
            if (this.additionalProperties[i] == null) {
                throw new ServiceValidationException_1.ServiceValidationException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.AdditionalPropertyIsNull, i));
            }
        }
    }
    /**
     * Removes the specified property from the set.
     *
     * @param   {PropertyDefinitionBase}    property   The property to remove.
     * @return  {boolean}                   true if the property was successfully removed, false otherwise.
     */
    Remove(property) {
        this.ThrowIfReadonly();
        return ExtensionMethods_1.ArrayHelper.RemoveEntry(this.additionalProperties, property);
    }
    /**
     * Throws if readonly property set.
     */
    ThrowIfReadonly() {
        if (this.isReadOnly) {
            throw new Error(" PropertySet can not be modified"); // System.NotSupportedException(Strings.PropertySetCannotBeModified);
        }
    }
    /**
     * Implements ISelfValidate.Validate. Validates this property set.
     */
    Validate() {
        this.InternalValidate();
    }
    /**
     * @internal Validates this property set instance for request to ensure that:
     *  1. Properties are valid for the request server version.
     *  2. If only summary properties are legal for this request (e.g. FindItem) then only summary properties were specified.
     *
     * @param   {ServiceRequestBase}    request                 The request.
     * @param   {boolean}               summaryPropertiesOnly   if set to true then only summary properties are allowed.
     */
    ValidateForRequest(request, summaryPropertiesOnly) {
        for (let propDefBase of this.additionalProperties) {
            //let propDefBase: PropertyDefinitionBase = propItem;
            let propertyDefinition = propDefBase;
            if (propertyDefinition instanceof PropertyDefinition_1.PropertyDefinition /* != null*/) {
                if (propertyDefinition.Version > request.Service.RequestedServerVersion) {
                    throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, propertyDefinition.Name, ExchangeVersion_1.ExchangeVersion[propertyDefinition.Version]));
                }
                if (summaryPropertiesOnly && !propertyDefinition.HasFlag(PropertyDefinitionFlags_1.PropertyDefinitionFlags.CanFind, request.Service.RequestedServerVersion)) {
                    throw new ServiceValidationException_1.ServiceValidationException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.NonSummaryPropertyCannotBeUsed, propertyDefinition.Name, request.GetXmlElementName()));
                }
            }
        }
        if (this.FilterHtmlContent /*.HasValue*/) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2010) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "FilterHtmlContent", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2010]));
            }
        }
        if (this.ConvertHtmlCodePageToUTF8 /*.HasValue*/) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2010_SP1) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "ConvertHtmlCodePageToUTF8", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2010_SP1]));
            }
        }
        if (!ExtensionMethods_1.StringHelper.IsNullOrEmpty(this.InlineImageUrlTemplate)) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "InlineImageUrlTemplate", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2013]));
            }
        }
        if (this.BlockExternalImages /*.HasValue*/) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "BlockExternalImages", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2013]));
            }
        }
        if (this.AddBlankTargetToLinks /*.HasValue*/) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "AddTargetToLinks", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2013]));
            }
        }
        if (this.MaximumBodySize /*.HasValue*/) {
            if (request.Service.RequestedServerVersion < ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                throw new ServiceVersionException_1.ServiceVersionException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PropertyIncompatibleWithRequestVersion, "MaximumBodySize", ExchangeVersion_1.ExchangeVersion[ExchangeVersion_1.ExchangeVersion.Exchange2013]));
            }
        }
    }
    /**
     * @internal Writes additonal properties to XML.
     *
     * @param   {EwsServiceXmlWriter}   writer                The writer to write to.
     * @param   {PropertyDefinitionBase[]}   propertyDefinitions   The property definitions to write.
     */
    static WriteAdditionalPropertiesToXml(writer, propertyDefinitions) {
        writer.WriteStartElement(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.AdditionalProperties);
        for (let propertyDefinition of propertyDefinitions) {
            propertyDefinition.WriteToXml(writer);
        }
        writer.WriteEndElement();
    }
    /**
     * @internal Writes the property set to XML.
     *
     * @param   {EwsServiceXmlWriter}   writer              The writer to write to.
     * @param   {ServiceObjectType}     serviceObjectType   The type of service object the property set is emitted for.
     */
    WriteToXml(writer, serviceObjectType) {
        let shapeElementName = PropertySet.GetShapeName(serviceObjectType);
        writer.WriteStartElement(XmlNamespace_1.XmlNamespace.Messages, shapeElementName);
        writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.BaseShape, PropertySet.defaultPropertySetMap.Member.get(this.BasePropertySet));
        if (serviceObjectType == ServiceObjectType_1.ServiceObjectType.Item) {
            if (this.RequestedBodyType /*.HasValue*/) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.BodyType, BodyType_1.BodyType[this.RequestedBodyType] /*.Value*/);
            }
            if (this.RequestedUniqueBodyType /*.HasValue*/) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.UniqueBodyType, BodyType_1.BodyType[this.RequestedUniqueBodyType] /*.Value*/);
            }
            if (this.RequestedNormalizedBodyType /*.HasValue*/) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.NormalizedBodyType, BodyType_1.BodyType[this.RequestedNormalizedBodyType] /*.Value*/);
            }
            if (this.FilterHtmlContent /*.HasValue*/) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.FilterHtmlContent, this.FilterHtmlContent /*.Value*/);
            }
            if (this.ConvertHtmlCodePageToUTF8 /*.HasValue*/ &&
                writer.Service.RequestedServerVersion >= ExchangeVersion_1.ExchangeVersion.Exchange2010_SP1) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.ConvertHtmlCodePageToUTF8, this.ConvertHtmlCodePageToUTF8 /*.Value*/);
            }
            if (!ExtensionMethods_1.StringHelper.IsNullOrEmpty(this.InlineImageUrlTemplate) &&
                writer.Service.RequestedServerVersion >= ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.InlineImageUrlTemplate, this.InlineImageUrlTemplate);
            }
            if (this.BlockExternalImages /*.HasValue*/ &&
                writer.Service.RequestedServerVersion >= ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.BlockExternalImages, this.BlockExternalImages /*.Value*/);
            }
            if (this.AddBlankTargetToLinks /*.HasValue*/ &&
                writer.Service.RequestedServerVersion >= ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.AddBlankTargetToLinks, this.AddBlankTargetToLinks /*.Value*/);
            }
            if (this.MaximumBodySize /*.HasValue*/ &&
                writer.Service.RequestedServerVersion >= ExchangeVersion_1.ExchangeVersion.Exchange2013) {
                writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.MaximumBodySize, this.MaximumBodySize /*.Value*/);
            }
        }
        if (this.additionalProperties.length > 0) {
            PropertySet.WriteAdditionalPropertiesToXml(writer, this.additionalProperties);
        }
        writer.WriteEndElement(); // Item/FolderShape
    }
}
exports.PropertySet = PropertySet;
/**
 * Returns a predefined property set that only includes the Id property.
 */
PropertySet.IdOnly = PropertySet.CreateReadonlyPropertySet(BasePropertySet_1.BasePropertySet.IdOnly);
/**
 * Returns a predefined property set that includes the first class properties of an item or folder.
 */
PropertySet.FirstClassProperties = PropertySet.CreateReadonlyPropertySet(BasePropertySet_1.BasePropertySet.FirstClassProperties);
/**
 * Maps BasePropertySet values to EWS's BaseShape values.
 */
PropertySet.defaultPropertySetMap = new LazyMember_1.LazyMember(() => {
    let result = new AltDictionary_1.Dictionary((bps) => BasePropertySet_1.BasePropertySet[bps]);
    result.Add(BasePropertySet_1.BasePropertySet.IdOnly, "IdOnly");
    result.Add(BasePropertySet_1.BasePropertySet.FirstClassProperties, "AllProperties");
    return result;
});
//# sourceMappingURL=PropertySet.js.map