/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */

import { InvalidMetadataError } from "#decoration/errors.js";
import { FieldModel } from "#models/FieldModel.js";
import type { Model } from "#models/Model.js";
import { InternalError } from "@matter/general";
import type { ClassSemantics } from "./ClassSemantics.js";
import { Semantics } from "./Semantics.js";

/**
 * Decorator metadata associated with a specific class field.
 */
export class FieldSemantics extends Semantics {
    #owner: ClassSemantics;

    constructor(owner: ClassSemantics, name: string) {
        super();
        this.#owner = owner;

        this.mutableModel = new FieldModel({ name, parent: owner.mutableModel });
    }

    get owner() {
        return this.#owner;
    }

    get semanticModel() {
        return this.localModel;
    }

    protected override createModel(): Model {
        // We create our model unconditionally so this shouldn't happen
        throw new InternalError("Unexpected FieldSemantics.createModel");
    }

    protected override integrateModel(model: Model): Model {
        if (this.localModel === undefined) {
            return model;
        }
        this.mutableModel.operationalBase = model;
        return this.mutableModel;
    }

    static override of(source: FieldSemantics.Source) {
        if (source.kind === "class") {
            throw new InvalidMetadataError(
                `Cannot retrieve field semantics for class decorator ${source.name ?? "of anonymous class"}`,
            );
        }
        return Semantics.classOf(source).fieldFor(source.name);
    }
}

export namespace FieldSemantics {
    export type Source = DecoratorContext;
}
