/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
/**
 * Lexical domain model for the Datalayer Client.
 *
 * @module models/LexicalDTO
 */
import * as lexicals from '../api/spacer/lexicals.js';
import { ItemTypes } from '../client/index.js';
import { ItemDTO } from './ItemDTO.js';
import { validateJSON } from '../api/utils/validation.js';
/**
 * Lexical domain model that extends the base Item class.
 * Provides lexical document functionality for managing rich text documents.
 *
 * @example
 * ```typescript
 * const lexical = await client.createLexical(formData);
 * await lexical.update({ name: 'Updated Documentation' });
 * ```
 */
export class LexicalDTO extends ItemDTO {
    /**
     * Create a Lexical instance.
     *
     * @param data - Lexical data from API
     * @param client - Client instance
     */
    constructor(data, client) {
        super(data, client);
    }
    // ========================================================================
    // Abstract Method Implementations
    // ========================================================================
    /** Document type identifier. */
    get type() {
        this._checkDeleted();
        return ItemTypes.LEXICAL;
    }
    /** The cached name of the document. */
    get name() {
        this._checkDeleted();
        return this._data.name_t || this._data.name || '';
    }
    /** Get the current name of the document from API. */
    async getName() {
        this._checkDeleted();
        const token = this._getToken();
        const spacerRunUrl = this._getSpacerRunUrl();
        const response = await lexicals.getLexical(token, this.uid, spacerRunUrl);
        if (response.document) {
            this._updateData(response.document);
            return response.document.name_t || response.document.name || '';
        }
        return this.name;
    }
    /** The cached content. */
    get content() {
        this._checkDeleted();
        if (!this._data.content && this._data.model_s) {
            try {
                return JSON.parse(this._data.model_s);
            }
            catch {
                return this._data.model_s;
            }
        }
        return this._data.content;
    }
    /** Description of the lexical document. */
    get description() {
        this._checkDeleted();
        return this._data.description_t || '';
    }
    /** Get the document extension. */
    get extension() {
        this._checkDeleted();
        const ext = this._data.document_extension_s;
        return ext ? (ext.startsWith('.') ? ext : `.${ext}`) : '.lexical';
    }
    /** Get when the document was last updated from API. */
    async getUpdatedAt() {
        this._checkDeleted();
        const token = this._getToken();
        const spacerRunUrl = this._getSpacerRunUrl();
        const response = await lexicals.getLexical(token, this.uid, spacerRunUrl);
        if (response.document) {
            this._updateData(response.document);
            const dateStr = response.document.last_update_ts_dt ||
                response.document.updated_at ||
                response.document.creation_ts_dt ||
                response.document.created_at;
            if (!dateStr) {
                throw new Error('No timestamp available for lexical document');
            }
            return new Date(dateStr);
        }
        const dateStr = this._data.last_update_ts_dt ||
            this._data.updated_at ||
            this._data.creation_ts_dt ||
            this._data.created_at;
        if (!dateStr) {
            throw new Error('No timestamp available for lexical document');
        }
        return new Date(dateStr);
    }
    /** Update the document. */
    async update(name, description) {
        // FIXME: check if both are needed, and use the existing values if only one provided
        this._checkDeleted();
        const token = this._getToken();
        const spacerRunUrl = this._getSpacerRunUrl();
        const updateData = {};
        if (name !== undefined)
            updateData.name = name;
        if (description !== undefined)
            updateData.description = description;
        const response = await lexicals.updateLexical(token, this.uid, updateData, spacerRunUrl);
        this._updateData(response.document);
        return this;
    }
    /**
     * Get lexical document data in camelCase format.
     * Returns only the core fields that consumers need.
     * This provides a stable interface regardless of API changes.
     *
     * @returns Core lexical data with camelCase properties
     */
    toJSON() {
        this._checkDeleted();
        const obj = {
            uid: this.uid,
            id: this.id,
            name: this.name,
            description: this.description,
            type: this.type,
            extension: this.extension,
            createdAt: this.createdAt.toDateString(),
            updatedAt: this.updatedAt.toDateString(),
            cdnUrl: this._data.cdn_url_s,
        };
        validateJSON(obj, 'Lexical');
        return obj;
    }
    /**
     * Get the raw lexical data exactly as received from the API.
     * This preserves the original snake_case naming from the API response.
     *
     * @returns Raw lexical data from API
     */
    rawData() {
        this._checkDeleted();
        return this._data;
    }
}
