import { Injectable, Injector, Optional, SkipSelf } from '@angular/core';
import { ActionHandler } from './action-handler.interface';
import { FEATURE_ACTION_HANDLERS, ROOT_ACTION_HANDLERS } from './tokens';

@Injectable()
export class CommandService {
  constructor(
    private injector: Injector,
    @Optional() @SkipSelf() private _parent: CommandService,
  ) {}

  async handleCommand<T>(command: string, data: T): Promise<T> {
    const actions = this.getActions(command);

    for (const action of actions) {
      const handler = this.getActionHandler(action);
      if (!handler) {
        console.error(
          'CommandService.handleCommand',
          'Action Handler does not exist',
          { action },
        );
        throw new Error('Action Handler does not exist');
      }
      data = await handler.handler(data, this);
    }
    return data;
  }

  getActions(command: string) {
    return command?.split('|') || [];
  }

  getActionHandler(action: string): ActionHandler | undefined {
    const featureActionHandlers: ActionHandler[] = this.injector.get(
      FEATURE_ACTION_HANDLERS,
      [],
    );
    const rootActionHandlers: ActionHandler[] = this.injector.get(
      ROOT_ACTION_HANDLERS,
      [],
    );

    let handler = [...featureActionHandlers, ...rootActionHandlers].find(
      (handler) => handler.action === action,
    );

    if (this._parent && !handler) {
      handler = this._parent.getActionHandler(action);
    }

    return handler;
  }
}
