0.0.1Updated a month ago
import type { Core } from "../core.ts";
import type { I_Plugin } from "./plugin.d.ts";
import type { PluginType, PluginTypeMap } from "./plugin_type.ts";
import type { Schema } from "./schema.ts";
import type { SchemaReference } from "./schema_reference.ts";

export interface Plugin<T extends Schema.Object, R extends Schema.Reference.Config> extends I_Plugin<T, R> {}
export class Plugin<T extends Schema.Object, R extends Schema.Reference.Config> {
  readonly core!: typeof Core

  readonly config!: Schema.Infer<T>
  readonly reference_map!: SchemaReference.MapLink<R>

  constructor(params: I_Plugin<T, R>) {
    this.slug = params.slug;
    this.name = params.name;
    this.version = params.version;
    this.config_schema = params.config_schema;
    this.defaults = params.defaults;
    this.references = params.references;
    this.init = params.init;
  }

  // deno-lint-ignore no-explicit-any
  private __services: Map<PluginType, any> = new Map();

  services<T extends PluginType>(type: T) {
    return (this.__services.get(type) || []) as PluginTypeMap[T][];
  }

  get data() {
    return new Proxy(this, { get(_this, p) {
      const reference_name = p.toString();
      const reference_data = (_this.references as R)[p as keyof R];
      if(!('$ref' in reference_data)) {
        if('multiple' in reference_data) return [];
        return null;
      }
      const reference_type = reference_data.$ref;

      const reference_id = _this.reference_map[reference_name];

      console.log({ [reference_name]: `Ref<${reference_type}::${reference_id}>` });

      return _this.core.Reference(reference_type, reference_id);
    }}) as unknown as SchemaReference.Map<R>;
  }

  hasService(type: PluginType) {
    return this.__services.has(type);
  }

  registerAs<T extends PluginType>(
    type: T,
    implementation: PluginTypeMap[T]
  ): this {
    if(!this.__services.has(type)) this.__services.set(type, []);
    this.__services.get(type)!.push(implementation);

    return this;
  }
}