"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FolderPermission = void 0;
const ExtensionMethods_1 = require("../ExtensionMethods");
const FolderPermissionLevel_1 = require("../Enumerations/FolderPermissionLevel");
const FolderPermissionReadAccess_1 = require("../Enumerations/FolderPermissionReadAccess");
const LazyMember_1 = require("../Core/LazyMember");
const PermissionScope_1 = require("../Enumerations/PermissionScope");
const ServiceLocalException_1 = require("../Exceptions/ServiceLocalException");
const ServiceValidationException_1 = require("../Exceptions/ServiceValidationException");
const Strings_1 = require("../Strings");
const UserId_1 = require("./UserId");
const XmlElementNames_1 = require("../Core/XmlElementNames");
const XmlNamespace_1 = require("../Enumerations/XmlNamespace");
const ComplexProperty_1 = require("./ComplexProperty");
/**
 * Represents a permission on a folder.
 *
 * @sealed
 */
class FolderPermission extends ComplexProperty_1.ComplexProperty {
    constructor(userIdOrStandardUserOrSmtpAddress, permissionLevel) {
        super();
        if (typeof userIdOrStandardUserOrSmtpAddress !== 'undefined' && typeof permissionLevel === 'undefined')
            throw new Error("FolderPermission - Constructor: permission level parameter cant be undefined or null when userid/smtpaddress/standarduser is provided in first place.");
        if (typeof userIdOrStandardUserOrSmtpAddress === 'undefined') {
            this.userId = new UserId_1.UserId();
        }
        else {
            this.permissionLevel = permissionLevel;
            if (typeof userIdOrStandardUserOrSmtpAddress === 'string' || typeof userIdOrStandardUserOrSmtpAddress === 'number') {
                this.userId = new UserId_1.UserId(userIdOrStandardUserOrSmtpAddress);
            }
            else {
                this.userId = userIdOrStandardUserOrSmtpAddress;
            }
        }
    }
    /**
     * Gets the Id of the user the permission applies to.
     */
    get UserId() {
        return this.userId;
    }
    set UserId(value) {
        if (this.userId != null) {
            ExtensionMethods_1.ArrayHelper.RemoveEntry(this.userId.OnChange, this.PropertyChanged);
        }
        this.SetFieldValue({ getValue: () => this.userId, setValue: (id) => this.userId = id }, value);
        if (this.userId != null) {
            this.userId.OnChange.push(this.PropertyChanged.bind(this));
        }
    }
    /**
     * Gets or sets a value indicating whether the user can create new items.
     */
    get CanCreateItems() {
        return this.canCreateItems;
    }
    set CanCreateItems(value) {
        this.SetFieldValue({ getValue: () => this.canCreateItems, setValue: (data) => this.canCreateItems = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating whether the user can create sub-folders.
     */
    get CanCreateSubFolders() {
        return this.canCreateSubFolders;
    }
    set CanCreateSubFolders(value) {
        this.SetFieldValue({ getValue: () => this.canCreateSubFolders, setValue: (data) => this.canCreateSubFolders = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating whether the user owns the folder.
     */
    get IsFolderOwner() {
        return this.isFolderOwner;
    }
    set IsFolderOwner(value) {
        this.SetFieldValue({ getValue: () => this.isFolderOwner, setValue: (data) => this.isFolderOwner = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating whether the folder is visible to the user.
     */
    get IsFolderVisible() {
        return this.isFolderVisible;
    }
    set IsFolderVisible(value) {
        this.SetFieldValue({ getValue: () => this.isFolderVisible, setValue: (data) => this.isFolderVisible = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating whether the user is a contact for the folder.
     */
    get IsFolderContact() {
        return this.isFolderContact;
    }
    set IsFolderContact(value) {
        this.SetFieldValue({ getValue: () => this.isFolderContact, setValue: (data) => this.isFolderContact = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating if/how the user can edit existing items.
     */
    get EditItems() {
        return this.editItems;
    }
    set EditItems(value) {
        this.SetFieldValue({ getValue: () => this.editItems, setValue: (data) => this.editItems = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets a value indicating if/how the user can delete existing items.
     */
    get DeleteItems() {
        return this.deleteItems;
    }
    set DeleteItems(value) {
        this.SetFieldValue({ getValue: () => this.deleteItems, setValue: (data) => this.deleteItems = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets the read items access permission.
     */
    get ReadItems() {
        return this.readItems;
    }
    set ReadItems(value) {
        this.SetFieldValue({ getValue: () => this.readItems, setValue: (data) => this.readItems = data }, value);
        this.AdjustPermissionLevel();
    }
    /**
     * Gets or sets the permission level.
     */
    get PermissionLevel() {
        return this.permissionLevel;
    }
    set PermissionLevel(value) {
        if (this.permissionLevel != value) {
            if (value == FolderPermissionLevel_1.FolderPermissionLevel.Custom) {
                throw new ServiceLocalException_1.ServiceLocalException(Strings_1.Strings.CannotSetPermissionLevelToCustom);
            }
            this.AssignIndividualPermissions(FolderPermission.defaultPermissions.Member[value]);
            this.SetFieldValue({ getValue: () => this.permissionLevel, setValue: (data) => this.permissionLevel = data }, value);
        }
    }
    /**
     * Gets the permission level that Outlook would display for this folder permission.
     */
    get DisplayPermissionLevel() {
        // If permission level is set to Custom, see if there's a variant
        // that Outlook would map to the same permission level.
        if (this.permissionLevel == FolderPermissionLevel_1.FolderPermissionLevel.Custom) {
            for (var variant of FolderPermission.levelVariants.Member) {
                if (this.IsEqualTo(variant)) {
                    return variant.PermissionLevel;
                }
            }
        }
        return this.permissionLevel;
    }
    /**
     * Determines the permission level of this folder permission based on its individual settings, and sets the PermissionLevel property accordingly.
     */
    AdjustPermissionLevel() {
        for (var key in FolderPermission.defaultPermissions.Member) {
            var value = FolderPermission.defaultPermissions.Member[key];
            if (this.IsEqualTo(value)) {
                this.permissionLevel = key;
                return;
            }
        }
        this.permissionLevel = FolderPermissionLevel_1.FolderPermissionLevel.Custom;
    }
    /**
     * Copies the values of the individual permissions of the specified folder permission to this folder permissions.
     *
     * @param   {FolderPermission}   permission   The folder permission to copy the values from.
     */
    AssignIndividualPermissions(permission) {
        this.canCreateItems = permission.CanCreateItems;
        this.canCreateSubFolders = permission.CanCreateSubFolders;
        this.isFolderContact = permission.IsFolderContact;
        this.isFolderOwner = permission.IsFolderOwner;
        this.isFolderVisible = permission.IsFolderVisible;
        this.editItems = permission.EditItems;
        this.deleteItems = permission.DeleteItems;
        this.readItems = permission.ReadItems;
    }
    /**
     * Create a copy of this FolderPermission instance.
     *
     * @return  {FolderPermission}      Clone of this instance.
     */
    Clone() {
        var res = new FolderPermission();
        res.canCreateItems = this.canCreateItems;
        res.canCreateSubFolders = this.canCreateSubFolders;
        res.deleteItems = this.deleteItems;
        res.editItems = this.editItems;
        res.isFolderContact = this.isFolderContact;
        res.isFolderOwner = this.isFolderOwner;
        res.isFolderVisible = this.isFolderVisible;
        res.permissionLevel = this.permissionLevel;
        res.readItems = this.readItems;
        res.userId = this.userId;
        return res;
    }
    /**
     * Determines whether the specified folder permission is the same as this one. The comparison does not take UserId and PermissionLevel into consideration.
     *
     * @param   {FolderPermission}  permission   The folder permission to compare with this folder permission.
     * @return  {boolean}           True is the specified folder permission is equal to this one, false otherwise.
     */
    IsEqualTo(permission) {
        return this.CanCreateItems == permission.CanCreateItems &&
            this.CanCreateSubFolders == permission.CanCreateSubFolders &&
            this.IsFolderContact == permission.IsFolderContact &&
            this.IsFolderVisible == permission.IsFolderVisible &&
            this.IsFolderOwner == permission.IsFolderOwner &&
            this.EditItems == permission.EditItems &&
            this.DeleteItems == permission.DeleteItems &&
            this.ReadItems == permission.ReadItems;
    }
    /**
     * @internal Loads service object from XML.
     *
     * @param   {any}				jsObject	Json Object converted from XML.
     * @param   {ExchangeService}	service	The service.
     */
    LoadFromXmlJsObject(jsObject /*JsonObject*/, service) {
        for (var key in jsObject) {
            switch (key) {
                case XmlElementNames_1.XmlElementNames.UserId:
                    this.UserId = new UserId_1.UserId();
                    this.UserId.LoadFromXmlJsObject(jsObject[key], service);
                    break;
                case XmlElementNames_1.XmlElementNames.CanCreateItems:
                    this.canCreateItems = ExtensionMethods_1.Convert.toBool(jsObject[key]);
                    break;
                case XmlElementNames_1.XmlElementNames.CanCreateSubFolders:
                    this.canCreateSubFolders = ExtensionMethods_1.Convert.toBool(jsObject[key]);
                    break;
                case XmlElementNames_1.XmlElementNames.IsFolderOwner:
                    this.isFolderOwner = ExtensionMethods_1.Convert.toBool(jsObject[key]);
                    break;
                case XmlElementNames_1.XmlElementNames.IsFolderVisible:
                    this.isFolderVisible = ExtensionMethods_1.Convert.toBool(jsObject[key]);
                    break;
                case XmlElementNames_1.XmlElementNames.IsFolderContact:
                    this.isFolderContact = ExtensionMethods_1.Convert.toBool(jsObject[key]);
                    break;
                case XmlElementNames_1.XmlElementNames.EditItems:
                    //debugger;//check for assignable enumeration type
                    this.editItems = PermissionScope_1.PermissionScope[jsObject[key]];
                    break;
                case XmlElementNames_1.XmlElementNames.DeleteItems:
                    //debugger;//check for assignable enumeration type
                    this.deleteItems = PermissionScope_1.PermissionScope[jsObject[key]];
                    break;
                case XmlElementNames_1.XmlElementNames.ReadItems:
                    //debugger;//check for assignable enumeration type
                    this.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess[jsObject[key]];
                    break;
                case XmlElementNames_1.XmlElementNames.PermissionLevel:
                case XmlElementNames_1.XmlElementNames.CalendarPermissionLevel:
                    //debugger;//check for assignable enumeration type
                    this.permissionLevel = FolderPermissionLevel_1.FolderPermissionLevel[jsObject[key]];
                    break;
                default:
                    break;
            }
        }
        this.AdjustPermissionLevel();
    }
    /**
     * Property was changed.
     *
     * @param   {ComplexProperty}   complexProperty   The complex property.
     */
    PropertyChanged(complexProperty) {
        this.Changed();
    }
    //Validate(isCalendarFolder: boolean, permissionIndex: number): void { throw new Error("FolderPermission.ts - Validate : Not implemented."); }
    /**
     * @internal Validates this instance.
     * ## parameters not optional: Typescript inheritance issue if not set as optional in code.
     *
     * @param   {boolean}   isCalendarFolder   if set to true calendar permissions are allowed.
     * @param   {number}    permissionIndex    Index of the permission.
     */
    Validate(isCalendarFolder, permissionIndex) {
        if (typeof isCalendarFolder === 'undefined' || typeof permissionIndex === 'undefined')
            throw new Error("FolderPermission - Validate: incorrect call to validate, without the isCalendar or permissionIndex pearameter. this signature makes it optional to comply with typescript inheritance system and to avoid compiletime error.");
        // Check UserId
        if (!this.UserId.IsValid()) {
            throw new ServiceValidationException_1.ServiceValidationException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.FolderPermissionHasInvalidUserId, permissionIndex));
        }
        // If this permission is to be used for a non-calendar folder make sure that read access and permission level aren't set to Calendar-only values
        if (!isCalendarFolder) {
            if ((this.readItems == FolderPermissionReadAccess_1.FolderPermissionReadAccess.TimeAndSubjectAndLocation) ||
                (this.readItems == FolderPermissionReadAccess_1.FolderPermissionReadAccess.TimeOnly)) {
                throw new ServiceLocalException_1.ServiceLocalException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.ReadAccessInvalidForNonCalendarFolder, this.readItems));
            }
            if ((this.permissionLevel == FolderPermissionLevel_1.FolderPermissionLevel.FreeBusyTimeAndSubjectAndLocation) ||
                (this.permissionLevel == FolderPermissionLevel_1.FolderPermissionLevel.FreeBusyTimeOnly)) {
                throw new ServiceLocalException_1.ServiceLocalException(ExtensionMethods_1.StringHelper.Format(Strings_1.Strings.PermissionLevelInvalidForNonCalendarFolder, FolderPermissionLevel_1.FolderPermissionLevel[this.permissionLevel]));
            }
        }
    }
    /**
     * @internal Writes elements to XML.
     *
     * @param   {EwsServiceXmlWriter}   writer             The writer.
     * @param   {boolean}               isCalendarFolder   If true, this permission is for a calendar folder.
     */
    WriteElementsToXml(writer, isCalendarFolder = false) {
        if (this.UserId != null) {
            this.UserId.WriteToXml(writer, XmlElementNames_1.XmlElementNames.UserId);
        }
        if (this.PermissionLevel == FolderPermissionLevel_1.FolderPermissionLevel.Custom) {
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.CanCreateItems, this.CanCreateItems);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.CanCreateSubFolders, this.CanCreateSubFolders);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.IsFolderOwner, this.IsFolderOwner);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.IsFolderVisible, this.IsFolderVisible);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.IsFolderContact, this.IsFolderContact);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.EditItems, this.EditItems);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.DeleteItems, this.DeleteItems);
            writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, XmlElementNames_1.XmlElementNames.ReadItems, this.ReadItems);
        }
        writer.WriteElementValue(XmlNamespace_1.XmlNamespace.Types, isCalendarFolder ? XmlElementNames_1.XmlElementNames.CalendarPermissionLevel : XmlElementNames_1.XmlElementNames.PermissionLevel, FolderPermissionLevel_1.FolderPermissionLevel[this.PermissionLevel]);
    }
    /**
     * @internal Writes to XML.
     *
     * @param   {EwsServiceXmlWriter}   writer             The writer.
     * @param   {string}                xmlElementName     Name of the XML element.
     * @param   {XmlNamespace}          xmlNamespace
     * @param   {isCalendarFolder}      isCalendarFolder   If true, this permission is for a calendar folder.
     */
    WriteToXml(writer, xmlElementName, xmlNamespace, isCalendarFolder = false) {
        writer.WriteStartElement(this.Namespace, xmlElementName);
        this.WriteAttributesToXml(writer);
        this.WriteElementsToXml(writer, isCalendarFolder);
        writer.WriteEndElement();
    }
}
exports.FolderPermission = FolderPermission;
FolderPermission.defaultPermissions = new LazyMember_1.LazyMember(() => {
    var result = {}; // new Dictionary<FolderPermissionLevel, FolderPermission>();
    var permission = new FolderPermission();
    permission.canCreateItems = false;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.None;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = false;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.None;
    result[FolderPermissionLevel_1.FolderPermissionLevel.None] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.None;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.None;
    result[FolderPermissionLevel_1.FolderPermissionLevel.Contributor] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = false;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.None;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.Reviewer] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.Owned;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.NoneditingAuthor] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.Owned;
    permission.editItems = PermissionScope_1.PermissionScope.Owned;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.Author] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = true;
    permission.deleteItems = PermissionScope_1.PermissionScope.Owned;
    permission.editItems = PermissionScope_1.PermissionScope.Owned;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.PublishingAuthor] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.All;
    permission.editItems = PermissionScope_1.PermissionScope.All;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.Editor] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = true;
    permission.deleteItems = PermissionScope_1.PermissionScope.All;
    permission.editItems = PermissionScope_1.PermissionScope.All;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.PublishingEditor] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = true;
    permission.canCreateSubFolders = true;
    permission.deleteItems = PermissionScope_1.PermissionScope.All;
    permission.editItems = PermissionScope_1.PermissionScope.All;
    permission.isFolderContact = true;
    permission.isFolderOwner = true;
    permission.isFolderVisible = true;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.FullDetails;
    result[FolderPermissionLevel_1.FolderPermissionLevel.Owner] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = false;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.None;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = false;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.TimeOnly;
    result[FolderPermissionLevel_1.FolderPermissionLevel.FreeBusyTimeOnly] = permission;
    permission = new FolderPermission();
    permission.canCreateItems = false;
    permission.canCreateSubFolders = false;
    permission.deleteItems = PermissionScope_1.PermissionScope.None;
    permission.editItems = PermissionScope_1.PermissionScope.None;
    permission.isFolderContact = false;
    permission.isFolderOwner = false;
    permission.isFolderVisible = false;
    permission.readItems = FolderPermissionReadAccess_1.FolderPermissionReadAccess.TimeAndSubjectAndLocation;
    result[FolderPermissionLevel_1.FolderPermissionLevel.FreeBusyTimeAndSubjectAndLocation] = permission;
    return result;
});
/**
 * Variants of pre-defined permission levels that Outlook also displays with the same levels.
 */
FolderPermission.levelVariants = new LazyMember_1.LazyMember(() => {
    var results = []; // new List<FolderPermission>();
    var permissionNone = FolderPermission.defaultPermissions.Member[FolderPermissionLevel_1.FolderPermissionLevel.None];
    var permissionOwner = FolderPermission.defaultPermissions.Member[FolderPermissionLevel_1.FolderPermissionLevel.Owner];
    // PermissionLevelNoneOption1
    var permission = permissionNone.Clone();
    permission.isFolderVisible = true;
    results.push(permission);
    // PermissionLevelNoneOption2
    permission = permissionNone.Clone();
    permission.isFolderContact = true;
    results.push(permission);
    // PermissionLevelNoneOption3
    permission = permissionNone.Clone();
    permission.isFolderContact = true;
    permission.isFolderVisible = true;
    results.push(permission);
    // PermissionLevelOwnerOption1
    permission = permissionOwner.Clone();
    permission.isFolderContact = false;
    results.push(permission);
    return results;
});
//# sourceMappingURL=FolderPermission.js.map