// 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;
  }
}
