import { HubItemEntity } from "../core/HubItemEntity";
import { fetchEvent } from "./fetch";
import { buildDefaultEventEntity } from "./defaults";
import { getEditorConfig } from "../core/schemas/getEditorConfig";
import { cloneObject } from "../util";
import { shareEventWithGroups } from "./_internal/shareEventWithGroups";
import { unshareEventWithGroups } from "./_internal/unshareEventWithGroups";
import HubError from "../HubError";
import { updateEvent } from "./api/events";
import { getEventGroups } from "./getEventGroups";
import { hubItemEntityFromEditor } from "../core/_internal/hubItemEntityFromEditor";
import { setProp } from "../objects/set-prop";
import { createHubEvent, deleteHubEvent, updateHubEvent } from "./edit";
/**
 * Defines the properties of a Hub Event object
 * @internal
 */
export class HubEvent extends HubItemEntity {
    /**
     * Create an instance from a HubEvent object
     * @param json - JSON object to create a HubEvent from
     * @param context - ArcGIS context
     * @returns HubEvent
     */
    static fromJson(json, context) {
        // merge what we have with the default values
        const pojo = this.applyDefaults(json, context);
        return new HubEvent(pojo, context);
    }
    /**
     * Fetch an Event from the API and return a HubEvent instance.
     * @param identifier slug or item id
     * @param context ArcGIS context
     * @returns Promise<HubEvent>
     */
    static async fetch(identifier, context) {
        try {
            const entity = await fetchEvent(identifier, context.hubRequestOptions);
            // create an instance of HubEvent from the entity
            return HubEvent.fromJson(entity, context);
        }
        catch (_ex) {
            throw new Error("Event not found.");
        }
    }
    static applyDefaults(partialEvent, context) {
        var _a;
        // ensure we have the orgUrlKey
        if (!partialEvent.orgUrlKey) {
            partialEvent.orgUrlKey = (_a = context.portal) === null || _a === void 0 ? void 0 : _a.urlKey;
        }
        // ensure orgUrlKey is lowercase
        if (partialEvent.orgUrlKey) {
            partialEvent.orgUrlKey = partialEvent.orgUrlKey.toLowerCase();
        }
        // extend the partial over the defaults
        const pojo = Object.assign(Object.assign({}, buildDefaultEventEntity()), partialEvent);
        return pojo;
    }
    /**
     * Apply a new state to the instance
     * @param changes A partial IHubEvent
     */
    update(changes) {
        if (this.isDestroyed) {
            throw new Error("HubEvent is already destroyed.");
        }
        this.entity = Object.assign(Object.assign({}, this.entity), changes);
    }
    /**
     * Creates or saves the Event.
     */
    async save() {
        if (this.isDestroyed) {
            throw new Error("HubEvent is already destroyed.");
        }
        if (this.entity.id) {
            this.entity = await updateHubEvent(this.entity, this.context.hubRequestOptions);
        }
        else {
            this.entity = await createHubEvent(this.entity, this.context.hubRequestOptions);
        }
        // not calling `afterSave` intentionally, doesn't apply to events
    }
    /**
     * Deletes the Event
     */
    async delete() {
        if (this.isDestroyed) {
            throw new Error("HubEvent is already destroyed.");
        }
        await deleteHubEvent(this.entity.id, this.context.hubRequestOptions);
        this.isDestroyed = true;
    }
    /**
     * Share the Entity with the specified group id
     * @param groupId The ID of the group to share the Event to
     */
    async shareWithGroup(groupId) {
        if (!this.context.currentUser) {
            throw new HubError("Share Event With Group", "Cannot share event with group when no user is logged in.");
        }
        this.entity = await shareEventWithGroups([groupId], this.entity, this.context);
    }
    /**
     * Share the Entity with the specified group ids
     * @param groupIds The IDs of the groups to share the Event to
     */
    async shareWithGroups(groupIds) {
        this.entity = await shareEventWithGroups(groupIds, this.entity, this.context);
    }
    /**
     * Unshare the Event with the specified group id
     * @param groupId The ID of the group to unshar ethe Event with
     */
    async unshareWithGroup(groupId) {
        this.entity = await unshareEventWithGroups([groupId], this.entity, this.context);
    }
    /**
     * Unshare the Event with the specified group ids
     * @param groupIds The IDs of the groups to unshare the Event with
     */
    async unshareWithGroups(groupIds) {
        this.entity = await unshareEventWithGroups(groupIds, this.entity, this.context);
    }
    /**
     * Sets the access level of the event
     * @param access The access level to set the Event to
     */
    async setAccess(access) {
        await updateEvent(Object.assign({ eventId: this.entity.id, data: {
                access: access.toUpperCase(),
            } }, this.context.hubRequestOptions));
        this.entity.access = access;
    }
    /**
     * Return a list of groups the Entity is shared to.
     */
    async sharedWith() {
        return getEventGroups(this.entity.id, this.context);
    }
    /*
     * Get the editor config for the HubEvent entity.
     * @param i18nScope translation scope to be interpolated into the uiSchema
     * @param type editor type - corresonds to the returned uiSchema
     * @returns Promise<IEditorConfig>
     */
    async getEditorConfig(i18nScope, type) {
        // delegate to the schema subsystem
        return getEditorConfig(i18nScope, type, this.entity, this.context);
    }
    /**
     * Return the HubEvent object as an editor object
     * @param editorContext
     * @param include
     * @returns Promise<IHubEventEditor>
     */
    async toEditor(_editorContext = {}, _include = []) {
        const editor = cloneObject(this.entity);
        return Promise.resolve(editor);
    }
    /**
     * Load the HubEvent object from the editor object
     * @param editor
     * @param editorContext
     * @returns Promise<IHubEvent>
     */
    async fromEditor(editor) {
        const thumbnail = editor._thumbnail;
        // delegate to an item-specific fromEditor util to
        // handle shared "fromEditor" logic
        const res = await hubItemEntityFromEditor(editor, this.context);
        const event = res.entity;
        // iterate over the res object keys and set the values
        // on the HubEvent instance
        Object.entries(res).forEach(([key, value]) => {
            setProp(key, value, this);
        });
        // 2. handle event-specific operations
        if (thumbnail) {
            event.thumbnailUrl = thumbnail.url || null;
        }
        // save or create the entity
        this.entity = event;
        await this.save();
        return this.entity;
    }
}
//# sourceMappingURL=HubEvent.js.map