import { DEFAULT_DISCUSSION } from "./defaults";
import { HubItemEntity } from "../core/HubItemEntity";
import { fetchDiscussion } from "./fetch";
import { getEditorConfig } from "../core/schemas/getEditorConfig";
import { cloneObject } from "../util";
import { enrichEntity } from "../core/enrichEntity";
import { getEditorSlug } from "../core/_internal/getEditorSlug";
import { truncateSlug } from "../items/_internal/slugs";
import { createDiscussion, deleteDiscussion, updateDiscussion } from "./edit";
/**
 * Hub Discussion Class
 */
export class HubDiscussion extends HubItemEntity {
    /**
     * Create an instance from an IHubDiscussion object
     * @param json JSON object to create a HubDiscussion from
     * @param context ArcGIS context
     * @returns a HubDiscussion
     */
    static fromJson(json, context) {
        // merge what we have with the default values
        const pojo = this.applyDefaults(json, context);
        return new HubDiscussion(pojo, context);
    }
    /**
     * Create a new HubDiscussion, returning a HubDiscussion instance.
     * Note: This does not persist the Discussion into the backing store
     * @param partialDiscussion a partial IHubDiscussion
     * @param context ArcGIS context
     * @returns promise that resolves a HubDiscussion
     */
    static async create(partialDiscussion, context, save = false) {
        const pojo = this.applyDefaults(partialDiscussion, context);
        // return an instance of HubDiscussion
        const instance = HubDiscussion.fromJson(pojo, context);
        if (save) {
            await instance.save();
        }
        return instance;
    }
    /**
     * Fetch a Discussion from the backing store and return a HubDiscussion instance.
     * @param identifier slug or item id
     * @param context ArcGIS context
     * @returns promise that resolves a HubDiscussion
     */
    static async fetch(identifier, context) {
        try {
            const entity = await fetchDiscussion(identifier, context.hubRequestOptions);
            // create an instance of HubDiscussion from the entity
            return HubDiscussion.fromJson(entity, context);
        }
        catch (ex) {
            throw ex.message ===
                "CONT_0001: Item does not exist or is inaccessible."
                ? new Error("Discussion not found.")
                : ex;
        }
    }
    static applyDefaults(partialDiscussion, context) {
        // ensure we have the orgUrlKey
        if (!partialDiscussion.orgUrlKey) {
            partialDiscussion.orgUrlKey = context.portal.urlKey;
        }
        // extend the partial over the defaults
        const pojo = Object.assign(Object.assign({}, DEFAULT_DISCUSSION), partialDiscussion);
        return pojo;
    }
    /**
     * Apply a new state to the instance
     * @param changes A partial IHubDiscussion
     */
    update(changes) {
        if (this.isDestroyed) {
            throw new Error("HubDiscussion is already destroyed.");
        }
        // merge partial onto existing entity
        this.entity = Object.assign(Object.assign({}, this.entity), changes);
    }
    async save() {
        if (this.isDestroyed) {
            throw new Error("HubDiscussion is already destroyed.");
        }
        if (this.entity.id) {
            // update it
            this.entity = await updateDiscussion(this.entity, this.context.hubRequestOptions);
        }
        else {
            // create it
            this.entity = await createDiscussion(this.entity, this.context.hubRequestOptions);
        }
        // call the after save hook on superclass
        await super.afterSave();
        return;
    }
    /**
     * Delete the HubDiscussion from the store
     * set a flag to indicate that it is destroyed
     * @returns a promise
     */
    async delete() {
        if (this.isDestroyed) {
            throw new Error("HubDiscussion is already destroyed.");
        }
        this.isDestroyed = true;
        // Delegate to module fn
        await deleteDiscussion(this.entity.id, this.context.hubRequestOptions);
    }
    /*
     * Get the editor config for the HubDiscussion entity.
     * @param i18nScope translation scope to be interpolated into the uiSchema
     * @param type editor type - corresonds to the returned uiSchema
     * @param options optional hash of dynamic uiSchema element options
     */
    async getEditorConfig(i18nScope, type) {
        // delegate to the schema subsystem
        return getEditorConfig(i18nScope, type, this.entity, this.context);
    }
    /**
     * Return the project as an editor object
     * @param editorContext
     * @returns
     */
    async toEditor(_editorContext = {}, include = []) {
        // 1. optionally enrich entity and cast to editor
        const editor = include.length
            ? (await enrichEntity(cloneObject(this.entity), include, this.context.hubRequestOptions))
            : cloneObject(this.entity);
        // 2. Apply transforms to relevant entity values so they
        // can be consumed by the editor
        editor._slug = getEditorSlug(this.entity);
        return editor;
    }
    /**
     * Load the project from the editor object
     * @param editor
     * @returns
     */
    async fromEditor(editor) {
        // TODO: Ideally we should delegate out to the
        // hubItemEntityFromEditor util to handle shared
        // "fromEditor" logic; however, when I attempted
        // to do this, I ran into issues with circular
        // dependencies and test failures that felt out
        // of scope for this work. For now, we'll copy
        // the relevant logic here.
        var _a;
        // 1. extract the ephemeral props we graft onto the
        // editor for later user
        const _thumbnail = editor._thumbnail;
        const _slug = editor._slug;
        // 2. remove the ephemeral props we graft onto the editor
        delete editor._thumbnail;
        delete editor._slug;
        const entity = cloneObject(editor);
        // 3. ensure orgUrlKey is set
        entity.orgUrlKey = editor.orgUrlKey
            ? editor.orgUrlKey
            : this.context.portal.urlKey || "";
        // ensure orgUrlKey is lowercase
        if (entity.orgUrlKey) {
            entity.orgUrlKey = entity.orgUrlKey.toLowerCase();
        }
        // 4. copy the configured location extent up one level
        // on the entity.
        entity.extent = (_a = editor.location) === null || _a === void 0 ? void 0 : _a.extent;
        // 5. Perform pre-save operations using the ephemeral
        // properties that were extracted above.
        // a. ensure the slug is truncated
        if (_slug) {
            // ensure the slug is truncated
            entity.slug = truncateSlug(_slug, entity.orgUrlKey);
        }
        else {
            // if no slug is passed in, save an empty string as
            // the slug, so that it is not saved as the orgUrlKey
            // truncated with an empty string
            entity.slug = "";
        }
        // b. conditionally set the thumbnailCache to
        // ensure that the configured thumbnail is updated
        // on the next save
        if (_thumbnail) {
            if (_thumbnail.blob) {
                this.thumbnailCache = {
                    file: _thumbnail.blob,
                    filename: _thumbnail.fileName,
                    clear: false,
                };
            }
            else {
                this.thumbnailCache = {
                    clear: true,
                };
            }
        }
        // Save, which will also create new content if new
        this.entity = entity;
        await this.save();
        return this.entity;
    }
}
//# sourceMappingURL=HubDiscussion.js.map