part of dart._engine;
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.



/// The type of a function that initializes an engine (in Dart).
typedef InitEngineFn = Future<void> Function([JsFlutterConfiguration? params]);

/// A class that controls the coarse lifecycle of a Flutter app.
class AppBootstrap {
  /// Construct an AppBootstrap.
  AppBootstrap({required InitEngineFn initializeEngine, required Function runApp}) :
    _initializeEngine = initializeEngine, _runApp = runApp;

  // A function to initialize the engine.
  final InitEngineFn _initializeEngine;

  // A function to run the app.
  //
  // TODO(dit): Be more strict with the typedef of this function, so we can add
  // typed params to the function. (See InitEngineFn).
  final Function _runApp;

  /// Immediately bootstraps the app.
  ///
  /// This calls `initEngine` and `runApp` in succession.
  Future<void> autoStart() async {
    await _initializeEngine();
    await _runApp();
  }

  /// Creates an engine initializer that runs our encapsulated initEngine function.
  FlutterEngineInitializer prepareEngineInitializer() {
    return FlutterEngineInitializer(
      // This is a convenience method that lets the programmer call "autoStart"
      // from JavaScript immediately after the main.dart.js has loaded.
      // Returns a promise that resolves to the Flutter app that was started.
      autoStart: allowInterop(() {
        return Promise<FlutterApp>(allowInterop((
          PromiseResolver<FlutterApp> resolve,
          PromiseRejecter _,
        ) async {
          await autoStart();
          // Return the App that was just started
          resolve(_prepareFlutterApp());
        }));
      }),
      // Calls [_initEngine], and returns a JS Promise that resolves to an
      // app runner object.
      initializeEngine: allowInterop(([JsFlutterConfiguration? configuration]) {
        // `params` coming from Javascript may be used to configure the engine intialization.
        // The internal `initEngine` function must accept those params.
        return Promise<FlutterAppRunner>(allowInterop((
          PromiseResolver<FlutterAppRunner> resolve,
          PromiseRejecter _,
        ) async {
          await _initializeEngine(configuration);
          // Return an app runner object
          resolve(_prepareAppRunner());
        }));
      }),
    );
  }

  /// Creates an appRunner that runs our encapsulated runApp function.
  FlutterAppRunner _prepareAppRunner() {
    return FlutterAppRunner(runApp: allowInterop(([RunAppFnParameters? params]) {
      // `params` coming from JS may be used to configure the run app method.
      return Promise<FlutterApp>(allowInterop((
        PromiseResolver<FlutterApp> resolve,
        PromiseRejecter _,
      ) async {
        await _runApp();
        // Return the App that was just started
        resolve(_prepareFlutterApp());
      }));
    }));
  }

  /// Represents the App that was just started, and its JS API.
  FlutterApp _prepareFlutterApp() {
    return FlutterApp();
  }
}
