"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HubTemplate = void 0;
const getEditorConfig_1 = require("../core/schemas/getEditorConfig");
const HubItemEntity_1 = require("../core/HubItemEntity");
const defaults_1 = require("./defaults");
const edit_1 = require("./edit");
const fetch_1 = require("./fetch");
const enrichEntity_1 = require("../core/enrichEntity");
const util_1 = require("../util");
const set_prop_1 = require("../objects/set-prop");
const hubItemEntityFromEditor_1 = require("../core/_internal/hubItemEntityFromEditor");
/**
 * Hub Template Class - this class encapsulates the standard
 * operations for a "Solution" item despite the Hub team not
 * "owning" this item type. Our primary goal is to allow
 * editing of the item's meta information, manage sharing, etc.
 */
class HubTemplate extends HubItemEntity_1.HubItemEntity {
    /**
     * Private constructor to allow for future
     * template-specific logic
     * @param template
     * @param context
     */
    constructor(template, context) {
        super(template, context);
    }
    /**
     * Create an HubTemplate instance from an IHubTemplate object
     * @param json - JSON object to create a HubTemplate from
     * @param context - ArcGIS context
     * @returns
     */
    static fromJson(json, context) {
        // merge what we have with the default values
        const pojo = this.applyDefaults(json, context);
        return new HubTemplate(pojo, context);
    }
    /**
     * Create a new HubTemplate, returning a HubTemplate instance.
     * This does not automatically persist the Template into
     * the backing store unless save is set to true
     *
     * NOTE: we have no immediate plans to allow template creation
     * from the context of the Hub application, but scaffolding this
     * method for potential future implementation. The underlying
     * createTemplate function will throw an error if attempted.
     * @param partialTemplate
     * @param context
     * @param save
     */
    static async create(partialTemplate, context, save = false) {
        const pojo = this.applyDefaults(partialTemplate, context);
        const instance = HubTemplate.fromJson(pojo, context);
        if (save) {
            await instance.save();
        }
        return instance;
    }
    /**
     * Fetch a HubTemplate from the backing store and return
     * a HubTemplate instance
     * @param identifier
     * @param context
     */
    static async fetch(identifier, context) {
        try {
            const initiativeTemplate = await (0, fetch_1.fetchTemplate)(identifier, context.requestOptions);
            return HubTemplate.fromJson(initiativeTemplate, context);
        }
        catch (ex) {
            if (ex.message ===
                "CONT_0001: Item does not exist or is inaccessible.") {
                throw new Error(`Template ${identifier} not found.`);
            }
            else {
                throw ex;
            }
        }
    }
    /**
     * Given a partial Template, apply defaults to
     * it to ensure that a baseline of properties are set
     * @param partialTemplate
     * @param context
     */
    static applyDefaults(partialTemplate, context) {
        // ensure we have the orgUrlKey
        if (!partialTemplate.orgUrlKey) {
            partialTemplate.orgUrlKey = context.portal.urlKey;
        }
        // ensure orgUrlKey is lowercase
        partialTemplate.orgUrlKey = partialTemplate.orgUrlKey.toLowerCase();
        // extend the partial over the defaults
        const pojo = Object.assign(Object.assign({}, defaults_1.DEFAULT_TEMPLATE), partialTemplate);
        return pojo;
    }
    /*
     * Get a specific editor config for the HubTemplate entity.
     * @param i18nScope
     * @param type
     */
    async getEditorConfig(i18nScope, type) {
        // delegate to the schema subsystem
        return (0, getEditorConfig_1.getEditorConfig)(i18nScope, type, this.entity, this.context);
    }
    /**
     * Transform template entity into an editor object
     * @param editorContext
     */
    async toEditor(_editorContext = {}, include = []) {
        // 1. optionally enrich entity and cast to editor
        const editor = include.length
            ? (await (0, enrichEntity_1.enrichEntity)((0, util_1.cloneObject)(this.entity), include, this.context.hubRequestOptions))
            : (0, util_1.cloneObject)(this.entity);
        // 2. Apply transforms to relevant entity values so they
        // can be consumed by the editor
        return editor;
    }
    /**
     * Transform editor values into a template entity
     * @param editor
     */
    async fromEditor(editor) {
        // delegate to an item-specific fromEditor util to
        // handle shared "fromEditor" logic
        const res = await (0, hubItemEntityFromEditor_1.hubItemEntityFromEditor)(editor, this.context);
        // iterate over the res object keys and set the values
        // on the HubTemplate instance
        Object.entries(res).forEach(([key, value]) => {
            (0, set_prop_1.setProp)(key, value, this);
        });
        // save, which will also create
        await this.save();
        return this.entity;
    }
    /**
     * Update the instance's internal entity state
     * @param changes
     */
    update(changes) {
        if (this.isDestroyed) {
            throw new Error("HubTemplate is already destroyed.");
        }
        this.entity = Object.assign(Object.assign({}, this.entity), changes);
    }
    /** Save the HubTemplate to the backing store */
    async save() {
        if (this.isDestroyed) {
            throw new Error("HubTemplate is already destroyed.");
        }
        // 1. create or update. Note: the underlying createTemplate
        // function will throw an error because we don't currently
        // allow for template creation from the context of Hub
        this.entity = this.entity.id
            ? await (0, edit_1.updateTemplate)(this.entity, this.context.userRequestOptions)
            : await (0, edit_1.createTemplate)(this.entity, this.context.userRequestOptions);
        // 2. call the after save hook on HubItemEntity superclass
        await super.afterSave();
    }
    /**
     * Delete the Hub Template's backing item and set a flag
     * indicating it's been destroyed
     */
    async delete() {
        if (this.isDestroyed) {
            throw new Error("HubTemplate is already destroyed.");
        }
        this.isDestroyed = true;
        await (0, edit_1.deleteTemplate)(this.entity.id, this.context.userRequestOptions);
    }
}
exports.HubTemplate = HubTemplate;
//# sourceMappingURL=HubTemplate.js.map