import { _rootModule } from "../shortcuts/attributes";
import { $attr } from "../shortcuts/queries";
import { UAttribute } from "./attribute";
import { UModel } from "./model";

export class UFeature {
  private _name: string;
  private _input?: UModel;
  private _output?: UModel;
  private _attributes: UAttribute<any>[] = [];

  constructor(name: string) {
    this._name = name;
  }

  $name() {
    return this._name;
  }

  $attribute<Type>(attribute: UAttribute<Type> | string) {
    const a = this._attributes.find((attr) =>
      typeof attribute == "string"
        ? attr.$name() == attribute
        : attr.$name() == attribute.$name()
    );
    return a ? a : null;
  }

  $attributes() {
    return [...this._attributes];
  }

  attributes(attributes: UAttribute<any>[]) {
    this.removeAttributes(attributes);
    this._attributes = this._attributes.concat(attributes);
    this._updateRootModule();
    return this;
  }

  $input() {
    return this._input;
  }

  $output() {
    return this._output;
  }

  input(model: UModel) {
    this._input = model;
    this._updateRootModule();
    return this;
  }

  output(model: UModel) {
    this._output = model;
    this._updateRootModule();
    return this;
  }

  _updateRootModule() {
    const rootModule = $attr(this, _rootModule());
    if (!rootModule) return;

    const input = this.$input();
    const output = this.$output();
    if (input && !$attr(input, _rootModule()))
      input.attributes([_rootModule(rootModule)]);
    if (output && !$attr(output, _rootModule()))
      output.attributes([_rootModule(rootModule)]);
  }

  removeAttributes(attributes: UAttribute<any>[]) {
    this._attributes = this._attributes.filter(
      (attribute) => !attributes.some((a) => a.$name() == attribute.$name())
    );
    return this;
  }
}
