"use strict";

import cloneDeepWith from 'lodash/cloneDeepWith';
import cloneDeep from 'lodash/cloneDeep';
import map from 'lodash/map';
import { CommandName } from "../interfaces/CommandName.js";
import { AndroidCustomRowForwarder } from "../adapters/AndroidCustomRowForwarder.js";
export class Commands {
  androidCustomRowForwarder = new AndroidCustomRowForwarder();
  constructor(store, nativeCommandsSender, layoutTreeParser, layoutTreeCrawler, commandsObserver, uniqueIdProvider, optionsProcessor, layoutProcessor, optionsCrawler) {
    this.store = store;
    this.nativeCommandsSender = nativeCommandsSender;
    this.layoutTreeParser = layoutTreeParser;
    this.layoutTreeCrawler = layoutTreeCrawler;
    this.commandsObserver = commandsObserver;
    this.uniqueIdProvider = uniqueIdProvider;
    this.optionsProcessor = optionsProcessor;
    this.layoutProcessor = layoutProcessor;
    this.optionsCrawler = optionsCrawler;
  }
  setRoot(simpleApi) {
    const input = cloneLayout(simpleApi);
    this.optionsCrawler.crawl(input.root);
    const processedRoot = this.layoutProcessor.process(input.root, CommandName.SetRoot);
    const root = this.layoutTreeParser.parse(processedRoot);
    const modals = map(input.modals, modal => {
      this.optionsCrawler.crawl(modal);
      const processedModal = this.layoutProcessor.process(modal, CommandName.SetRoot);
      return this.layoutTreeParser.parse(processedModal);
    });
    const overlays = map(input.overlays, overlay => {
      this.optionsCrawler.crawl(overlay);
      const processedOverlay = this.layoutProcessor.process(overlay, CommandName.SetRoot);
      return this.layoutTreeParser.parse(processedOverlay);
    });
    const commandId = this.uniqueIdProvider.generate(CommandName.SetRoot);
    this.commandsObserver.notify(CommandName.SetRoot, {
      commandId,
      layout: {
        root,
        modals,
        overlays
      }
    });
    this.layoutTreeCrawler.crawl(root, CommandName.SetRoot);
    modals.forEach(modalLayout => {
      this.layoutTreeCrawler.crawl(modalLayout, CommandName.SetRoot);
    });
    overlays.forEach(overlayLayout => {
      this.layoutTreeCrawler.crawl(overlayLayout, CommandName.SetRoot);
    });
    this.androidCustomRowForwarder.forwardFromLayouts([root, ...modals, ...overlays]);
    const result = this.nativeCommandsSender.setRoot(commandId, {
      root,
      modals,
      overlays
    });
    return result;
  }
  setDefaultOptions(options) {
    const input = cloneDeep(options);
    this.optionsProcessor.processDefaultOptions(input, CommandName.SetDefaultOptions);
    this.androidCustomRowForwarder.forwardFromOptions(input);
    this.nativeCommandsSender.setDefaultOptions(input);
    this.commandsObserver.notify(CommandName.SetDefaultOptions, {
      options
    });
  }
  mergeOptions(componentId, options) {
    const input = cloneDeep(options);
    const component = this.store.getComponentInstance(componentId);
    const componentProps = this.store.getPropsForId(componentId) || undefined;
    this.optionsProcessor.processOptions(CommandName.MergeOptions, input, componentProps);
    if (component && !component.isMounted) console.warn(`Navigation.mergeOptions was invoked on component with id: ${componentId} before it is mounted, this can cause UI issues and should be avoided.\n Use static options instead.`);
    this.androidCustomRowForwarder.forwardFromOptions(input);
    this.nativeCommandsSender.mergeOptions(componentId, input);
    this.commandsObserver.notify(CommandName.MergeOptions, {
      componentId,
      options
    });
  }
  updateProps(componentId, props, callback) {
    this.store.updateProps(componentId, props, callback);
    this.commandsObserver.notify(CommandName.UpdateProps, {
      componentId,
      props
    });
  }
  showModal(layout) {
    const layoutCloned = cloneLayout(layout);
    this.optionsCrawler.crawl(layoutCloned);
    const layoutProcessed = this.layoutProcessor.process(layoutCloned, CommandName.ShowModal);
    const layoutNode = this.layoutTreeParser.parse(layoutProcessed);
    const commandId = this.uniqueIdProvider.generate(CommandName.ShowModal);
    this.commandsObserver.notify(CommandName.ShowModal, {
      commandId,
      layout: layoutNode
    });
    this.layoutTreeCrawler.crawl(layoutNode, CommandName.ShowModal);
    this.androidCustomRowForwarder.forwardFromLayout(layoutNode);
    const result = this.nativeCommandsSender.showModal(commandId, layoutNode);
    return result;
  }
  dismissModal(componentId, mergeOptions) {
    const commandId = this.uniqueIdProvider.generate(CommandName.DismissModal);
    this.optionsProcessor.processOptions(CommandName.DismissModal, mergeOptions);
    const result = this.nativeCommandsSender.dismissModal(commandId, componentId, mergeOptions);
    this.commandsObserver.notify(CommandName.DismissModal, {
      commandId,
      componentId,
      mergeOptions
    });
    return result;
  }
  dismissAllModals(mergeOptions) {
    const commandId = this.uniqueIdProvider.generate(CommandName.DismissAllModals);
    this.optionsProcessor.processOptions(CommandName.DismissAllModals, mergeOptions);
    const result = this.nativeCommandsSender.dismissAllModals(commandId, mergeOptions);
    this.commandsObserver.notify(CommandName.DismissAllModals, {
      commandId,
      mergeOptions
    });
    return result;
  }
  push(componentId, simpleApi) {
    const input = cloneLayout(simpleApi);
    this.optionsCrawler.crawl(input);
    const layoutProcessed = this.layoutProcessor.process(input, CommandName.Push);
    const layout = this.layoutTreeParser.parse(layoutProcessed);
    const commandId = this.uniqueIdProvider.generate(CommandName.Push);
    this.commandsObserver.notify(CommandName.Push, {
      commandId,
      componentId,
      layout
    });
    this.layoutTreeCrawler.crawl(layout, CommandName.Push);
    this.androidCustomRowForwarder.forwardFromLayout(layout);
    const result = this.nativeCommandsSender.push(commandId, componentId, layout);
    return result;
  }
  pop(componentId, mergeOptions) {
    const commandId = this.uniqueIdProvider.generate(CommandName.Pop);
    this.optionsProcessor.processOptions(CommandName.Pop, mergeOptions);
    const result = this.nativeCommandsSender.pop(commandId, componentId, mergeOptions);
    this.commandsObserver.notify(CommandName.Pop, {
      commandId,
      componentId,
      mergeOptions
    });
    return result;
  }
  popTo(componentId, mergeOptions) {
    const commandId = this.uniqueIdProvider.generate(CommandName.PopTo);
    this.optionsProcessor.processOptions(CommandName.PopTo, mergeOptions);
    const result = this.nativeCommandsSender.popTo(commandId, componentId, mergeOptions);
    this.commandsObserver.notify(CommandName.PopTo, {
      commandId,
      componentId,
      mergeOptions
    });
    return result;
  }
  popToRoot(componentId, mergeOptions) {
    const commandId = this.uniqueIdProvider.generate(CommandName.PopToRoot);
    this.optionsProcessor.processOptions(CommandName.PopToRoot, mergeOptions);
    const result = this.nativeCommandsSender.popToRoot(commandId, componentId, mergeOptions);
    this.commandsObserver.notify(CommandName.PopToRoot, {
      commandId,
      componentId,
      mergeOptions
    });
    return result;
  }
  setStackRoot(componentId, children) {
    const input = map(cloneLayout(children), simpleApi => {
      this.optionsCrawler.crawl(simpleApi);
      const layoutProcessed = this.layoutProcessor.process(simpleApi, CommandName.SetStackRoot);
      const layout = this.layoutTreeParser.parse(layoutProcessed);
      return layout;
    });
    const commandId = this.uniqueIdProvider.generate(CommandName.SetStackRoot);
    this.commandsObserver.notify(CommandName.SetStackRoot, {
      commandId,
      componentId,
      layout: input
    });
    input.forEach(layoutNode => {
      this.layoutTreeCrawler.crawl(layoutNode, CommandName.SetStackRoot);
    });
    this.androidCustomRowForwarder.forwardFromLayouts(input);
    const result = this.nativeCommandsSender.setStackRoot(commandId, componentId, input);
    return result;
  }
  showOverlay(simpleApi) {
    const input = cloneLayout(simpleApi);
    this.optionsCrawler.crawl(input);
    const layoutProcessed = this.layoutProcessor.process(input, CommandName.ShowOverlay);
    const layout = this.layoutTreeParser.parse(layoutProcessed);
    const commandId = this.uniqueIdProvider.generate(CommandName.ShowOverlay);
    this.commandsObserver.notify(CommandName.ShowOverlay, {
      commandId,
      layout
    });
    this.layoutTreeCrawler.crawl(layout, CommandName.ShowOverlay);
    const result = this.nativeCommandsSender.showOverlay(commandId, layout);
    return result;
  }
  dismissOverlay(componentId) {
    const commandId = this.uniqueIdProvider.generate(CommandName.DismissOverlay);
    const result = this.nativeCommandsSender.dismissOverlay(commandId, componentId);
    this.commandsObserver.notify(CommandName.DismissOverlay, {
      commandId,
      componentId
    });
    return result;
  }
  dismissAllOverlays() {
    const commandId = this.uniqueIdProvider.generate(CommandName.DismissAllOverlays);
    const result = this.nativeCommandsSender.dismissAllOverlays(commandId);
    this.commandsObserver.notify(CommandName.DismissAllOverlays, {
      commandId
    });
    return result;
  }
  getLaunchArgs() {
    const commandId = this.uniqueIdProvider.generate(CommandName.GetLaunchArgs);
    const result = this.nativeCommandsSender.getLaunchArgs(commandId);
    this.commandsObserver.notify(CommandName.GetLaunchArgs, {
      commandId
    });
    return result;
  }
}
function cloneLayout(layout) {
  return cloneDeepWith(layout, (value, key) => {
    if (key === 'passProps' && typeof value === 'object' && value !== null) return {
      ...value
    };
  });
}
//# sourceMappingURL=Commands.js.map