import { nanoid } from '../nanoid.js';
import { Property, Kind as PropertyKind } from './Property.js';
export const Kind = 'Core#ProjectSchema';
/**
 * A project can contain schema definitions that can be reused in project requests.
 * The schema consists of:
 *
 * - content: the "raw" schema value in any format. This goes unprocessed into the request body.
 * - properties: a map of properties description that can be manipulated at runtime
 *
 * Scalar values are not supported as a schema definition. It always represents an object.
 */
export class ProjectSchema {
    kind = Kind;
    /**
     * The identifier of the environment.
     */
    key = '';
    /**
     * The optional list of properties in this schema.
     * Because this is a list instead of a map it is possible to duplicate the property name. In this
     * case the last set value is the final value.
     *
     * When both the `properties` and the `content` is defined, `content` is used instead of properties.
     */
    properties;
    /**
     * The "raw" content of the schema.
     * This value goes unchanged to the request.
     */
    content;
    /**
     * When content is used, it informs about the content type of the
     * schema. The schema is invalid when `content` is set and the `mime` is not.
     */
    mime;
    /**
     * The name of the schema.
     */
    name = '';
    /**
     * Creates a new schema instance from the passed name.
     * @param name The name of the schema.
     */
    static fromName(name) {
        const init = {
            kind: Kind,
            name,
            key: nanoid(),
        };
        return new ProjectSchema(init);
    }
    /**
     * Creates a new schema instance from the content definition
     * @param name The name of the schema.
     * @param content The "raw" content of the schema
     * @param mime The mime type associated with the schema.
     * @returns The instance of the created schema
     */
    static fromContent(name, content, mime) {
        const init = {
            kind: Kind,
            name,
            key: nanoid(),
            content,
            mime,
        };
        return new ProjectSchema(init);
    }
    /**
     * @param input The schema definition used to restore the state.
     */
    constructor(input) {
        let init;
        if (typeof input === 'string') {
            init = JSON.parse(input);
        }
        else if (typeof input === 'object') {
            init = input;
        }
        else {
            init = {
                kind: Kind,
                name: '',
                key: nanoid(),
            };
        }
        this.new(init);
    }
    /**
     * Creates a new schema definition clearing anything that is so far defined.
     */
    new(init) {
        const { key = nanoid(), content, properties, mime, name = '' } = init;
        this.name = name;
        this.key = key;
        if (content) {
            this.content = content;
        }
        else {
            this.content = undefined;
        }
        if (Array.isArray(properties)) {
            this.properties = properties.map((i) => new Property(i));
        }
        else {
            this.properties = undefined;
        }
        if (mime) {
            this.mime = mime;
        }
        else {
            this.mime = undefined;
        }
    }
    toJSON() {
        const result = {
            kind: Kind,
            name: this.name || '',
            key: this.key || nanoid(),
        };
        if (this.content) {
            result.content = this.content;
        }
        if (this.mime) {
            result.mime = this.mime;
        }
        if (Array.isArray(this.properties) && this.properties.length) {
            result.properties = this.properties.map((i) => i.toJSON());
        }
        return result;
    }
    addProperty(infoOrName, type) {
        const infoType = typeof infoOrName;
        if (infoType === 'string' && !type) {
            throw new Error('The type is required.');
        }
        let instance;
        if (infoType === 'string') {
            instance = Property.fromTypeDefault(infoOrName, type);
        }
        else {
            const init = infoOrName;
            if (!init.kind) {
                init.kind = PropertyKind;
            }
            instance = new Property(init);
        }
        if (!Array.isArray(this.properties)) {
            this.properties = [];
        }
        this.properties.push(instance);
        return instance;
    }
}
//# sourceMappingURL=ProjectSchema.js.map