import { Access } from '../loader/Permission';
import { PredefinedBimChangeMetadataQuery } from '../loader/PredefinedBimChangeMetadataQuery';
import { path } from '../Path';
import { isFailure } from '../fail';
import { asWriteable } from '../Types';
/**
 * Represents the Layer Attachments API.
 * Contains methods to work with layer attachments for a specific layer.
 * @alpha This class is not fully tested yet. Use with caution.
 */
export class LayerAttachmentsApi {
    _clientApi;
    _parent;
    /**
     * Creates a new instance of the LayerAttachmentsApiImpl class.
     * @param _clientApi The TwinfinityApiClient instance.
     * @param _parent The parent object containing the layer and permission-related methods.
     */
    constructor(_clientApi, _parent) {
        this._clientApi = _clientApi;
        this._parent = _parent;
    }
    /**
     * Adds a new attachment to the layer.
     * @param options The options for creating the attachment.
     * @returns A promise that resolves to the created attachment or an error.
     */
    async add(options) {
        this._parent.throwIfNoPermissionsAreSatisfied(Access.add);
        return this._clientApi.upload.createFileSession({
            ...options,
            operation: 'create',
            parent: this._parent.layer
        });
    }
    /**
     * Checks if the given change is an attachment of the layer.
     * @param change The change to check.
     * @returns True if the change is an attachment of the layer, false otherwise.
     */
    isAttachment(change) {
        // Attachmenst are changes with a layer as a parent (instead of a folder).
        return path(change.path)?.parent?.equals(this._parent.layer.path) === true;
    }
    /**
     * Determines whether the caller has sufficient permissions to add attachments to the layer.
     * @returns True if attachments can be added to the layer, false otherwise.
     */
    canAdd() {
        const layer = this._parent.layer;
        return this._clientApi.upload.canCreateFileIn(layer);
    }
    /**
     * Determines whether the caller has sufficient permissions to update a attachment (create a new version of it) on the layer.
     * @param attachment The attachment to check.
     * @returns True if the attachment can be updated (new version created), false otherwise.
     */
    canUpdate(attachment) {
        return this._clientApi.upload.canAppendFileVersion(attachment);
    }
    /**
     * Retrieves all attachments of the layer (may be none).
     * @returns List of attachments.
     */
    async get() {
        const layer = this._parent.layer;
        const resp = await this._clientApi.getChanges(layer, PredefinedBimChangeMetadataQuery.all());
        if (isFailure(resp))
            return resp;
        // getChanges returns children + the layer itself as a change, so we need to exclude
        // the layer to only get the attachments.
        const excludeLayerChange = async (changesPromise) => {
            return (await changesPromise).filter((change) => change.id !== layer.id);
        };
        asWriteable(resp).value = excludeLayerChange(resp.value);
        return resp;
    }
    /**
     * Updates an existing attachment with a new version.
     * @param attachment The attachment to update.
     * @param options The options for updating the attachment.
     * @returns A promise that resolves to the updated attachment or an error.
     */
    async update(attachment, options) {
        this._parent.throwIfNoPermissionsAreSatisfied(Access.edit);
        this.throwIfAttachmentDoesNotBelongToLayer(attachment);
        return this._clientApi.upload.createFileSession({
            ...options,
            operation: 'append',
            previousVersion: attachment
        });
    }
    /**
     * Deletes the specified attachments from the layer.
     * @param changes The attachments to delete.
     * @returns A promise that resolves to the number of deleted attachments or an error.
     */
    delete(changes) {
        changes.forEach((attachment) => this.throwIfAttachmentDoesNotBelongToLayer(attachment));
        return this._clientApi.deleteChanges(changes);
    }
    /**
     * Throws an error if the attachment does not belong to the layer.
     * @param attachment The attachment to check.
     */
    throwIfAttachmentDoesNotBelongToLayer(attachment) {
        if (!this.isAttachment(attachment))
            throw new Error(`Change ${attachment.path} does not belong to layer ${this._parent.layer.path}.`);
    }
}
//# sourceMappingURL=LayerAttachmentsApi.js.map