// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

export type ControllerAny = Controller</* StateType=*/ unknown>;

export interface ControllerFactory<ConstructorArgs> {
  new (args: ConstructorArgs): ControllerAny;
}

interface ControllerInitializer<ConstructorArgs> {
  id: string;
  factory: ControllerFactory<ConstructorArgs>;
  args: ConstructorArgs;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ControllerInitializerAny = ControllerInitializer<any>;

export function Child<ConstructorArgs>(
  id: string,
  factory: ControllerFactory<ConstructorArgs>,
  args: ConstructorArgs,
): ControllerInitializer<ConstructorArgs> {
  return {id, factory, args};
}

export type Children = ControllerInitializerAny[];

export abstract class Controller<StateType> {
  // This is about the local FSM state, has nothing to do with the global
  // app state.
  private _stateChanged = false;
  private _inRunner = false;
  private _state: StateType;
  private _children = new Map<string, ControllerAny>();

  constructor(initialState: StateType) {
    this._state = initialState;
  }

  abstract run(): Children | void;
  onDestroy(): void {}

  // Invokes the current controller subtree, recursing into children.
  // While doing so handles lifecycle of child controllers.
  // This method should be called only by the runControllers() method in
  // globals.ts. Exposed publicly for testing.
  invoke(): boolean {
    if (this._inRunner) throw new Error('Reentrancy in Controller');
    this._stateChanged = false;
    this._inRunner = true;
    const resArray = this.run();
    let triggerAnotherRun = this._stateChanged;
    this._stateChanged = false;

    const nextChildren = new Map<string, ControllerInitializerAny>();
    if (resArray !== undefined) {
      for (const childConfig of resArray) {
        if (nextChildren.has(childConfig.id)) {
          throw new Error(`Duplicate children controller ${childConfig.id}`);
        }
        nextChildren.set(childConfig.id, childConfig);
      }
    }
    const dtors = new Array<() => void>();
    const runners = new Array<() => boolean>();
    for (const key of this._children.keys()) {
      if (nextChildren.has(key)) continue;
      const instance = this._children.get(key)!;
      this._children.delete(key);
      dtors.push(() => instance.onDestroy());
    }
    for (const nextChild of nextChildren.values()) {
      if (!this._children.has(nextChild.id)) {
        const instance = new nextChild.factory(nextChild.args);
        this._children.set(nextChild.id, instance);
      }
      const instance = this._children.get(nextChild.id)!;
      runners.push(() => instance.invoke());
    }

    for (const dtor of dtors) dtor(); // Invoke all onDestroy()s.

    // Invoke all runner()s.
    for (const runner of runners) {
      const recursiveRes = runner();
      triggerAnotherRun = triggerAnotherRun || recursiveRes;
    }

    this._inRunner = false;
    return triggerAnotherRun;
  }

  setState(state: StateType) {
    if (!this._inRunner) {
      throw new Error('Cannot setState() outside of the run() method');
    }
    this._stateChanged = state !== this._state;
    this._state = state;
  }

  get state(): StateType {
    return this._state;
  }
}
