"use strict";

import clone from 'lodash/clone';
import isEqual from 'lodash/isEqual';
import isObject from 'lodash/isObject';
import isArray from 'lodash/isArray';
import isString from 'lodash/isString';
import endsWith from 'lodash/endsWith';
import forEach from 'lodash/forEach';
import has from 'lodash/has';
import { Platform, DynamicColorIOS } from 'react-native';
export class OptionsProcessor {
  constructor(store, uniqueIdProvider, optionProcessorsRegistry, colorService, assetService, deprecations) {
    this.store = store;
    this.uniqueIdProvider = uniqueIdProvider;
    this.optionProcessorsRegistry = optionProcessorsRegistry;
    this.colorService = colorService;
    this.assetService = assetService;
    this.deprecations = deprecations;
  }
  processOptions(commandName, options, props) {
    if (options) {
      this.processObject(options, clone(options), (key, parentOptions) => {
        this.deprecations.onProcessOptions(key, parentOptions, commandName);
        this.deprecations.checkForDeprecatedOptions(parentOptions);
      }, commandName, props);
    }
  }
  processDefaultOptions(options, commandName) {
    this.processObject(options, clone(options), (key, parentOptions) => {
      this.deprecations.onProcessDefaultOptions(key, parentOptions);
    }, commandName);
  }
  processObject(objectToProcess, parentOptions, onProcess, commandName, props, parentPath) {
    forEach(objectToProcess, (value, key) => {
      const objectPath = this.resolveObjectPath(key, parentPath);
      this.processWithRegisteredProcessor(key, value, objectToProcess, objectPath, commandName, props);
      this.processColor(key, value, objectToProcess);
      if (!value) {
        return;
      }
      this.processComponent(key, value, objectToProcess);
      this.processImage(key, value, objectToProcess);
      this.processButtonsPassProps(key, value);
      this.processSearchBar(key, value, objectToProcess);
      this.processInterpolation(key, value, objectToProcess);
      this.processAnimation(key, value, objectToProcess);
      onProcess(key, parentOptions);
      const processedValue = objectToProcess[key];
      if (!isEqual(key, 'passProps') && (isObject(processedValue) || isArray(processedValue))) {
        this.processObject(processedValue, parentOptions, onProcess, commandName, props, objectPath);
      }
    });
  }
  resolveObjectPath(key, path) {
    if (!path) path = key;else path += `.${key}`;
    return path;
  }
  processColor(key, value, options) {
    if ((isEqual(key, 'color') || endsWith(key, 'Color')) && !isEqual(key, 'bkgColor')) {
      if (Platform.OS === 'ios') this.processColorIOS(key, value, options);else this.processColorAndroid(key, value, options);
    }
  }
  processColorIOS(key, value, options) {
    if (value !== undefined) {
      if (value === null) {
        options[key] = 'NoColor';
      } else if (value instanceof Object) {
        if ('semantic' in value) {
          options[key] = value;
        } else if ('dynamic' in value) {
          options[key] = DynamicColorIOS({
            light: this.colorService.toNativeColor(value.dynamic.light),
            dark: this.colorService.toNativeColor(value.dynamic.dark)
          });
        } else {
          options[key] = DynamicColorIOS({
            light: this.colorService.toNativeColor(value.light),
            dark: this.colorService.toNativeColor(value.dark)
          });
        }
      } else {
        options[key] = this.colorService.toNativeColor(value);
      }
    }
  }
  processColorAndroid(key, value, options) {
    if (value !== undefined) {
      const newColorObj = {
        dark: 'NoColor',
        light: 'NoColor'
      };
      if (value === null) {
        options[key] = newColorObj;
      } else if (value instanceof Object) {
        if ('semantic' in value || 'resource_paths' in value) {
          options[key] = value;
          return;
        } else {
          for (let keyColor in value) {
            newColorObj[keyColor] = this.colorService.toNativeColor(value[keyColor]);
          }
          options[key] = newColorObj;
        }
      } else {
        let parsedColor = this.colorService.toNativeColor(value);
        newColorObj.light = parsedColor;
        newColorObj.dark = parsedColor;
        options[key] = newColorObj;
      }
    }
  }
  processWithRegisteredProcessor(key, value, options, path, commandName, passProps) {
    const registeredProcessors = this.optionProcessorsRegistry.getProcessors(path);
    if (registeredProcessors) {
      registeredProcessors.forEach(processor => {
        options[key] = processor(value, commandName, passProps);
      });
    }
  }
  processImage(key, value, options) {
    if (isEqual(key, 'icon') || isEqual(key, 'image') || endsWith(key, 'Icon') || endsWith(key, 'Image')) {
      options[key] = isString(value) ? value : this.assetService.resolveFromRequire(value);
    }
  }
  processButtonsPassProps(key, value) {
    if (endsWith(key, 'Buttons')) {
      forEach(value, button => {
        if (button.passProps && button.id) {
          this.store.setPendingProps(button.id, button.passProps);
          button.passProps = undefined;
        }
      });
    }
  }
  processComponent(key, value, options) {
    if (isEqual(key, 'component')) {
      value.componentId = value.id ? value.id : this.uniqueIdProvider.generate('CustomComponent');
      this.store.ensureClassForName(value.name);
      if (value.passProps) {
        this.store.setPendingProps(value.componentId, value.passProps);
      }
      options[key].passProps = undefined;
    }
  }
  processSearchBar(key, value, options) {
    if (key !== 'searchBar') {
      return;
    }
    const deprecatedSearchBarOptions = {
      visible: false,
      hideOnScroll: options.searchBarHiddenWhenScrolling ?? false,
      hideTopBarOnFocus: options.hideNavBarOnFocusSearchBar ?? false,
      obscuresBackgroundDuringPresentation: false,
      backgroundColor: options.searchBarBackgroundColor,
      tintColor: options.searchBarTintColor,
      placeholder: options.searchBarPlaceholder ?? ''
    };
    if (typeof value === 'boolean') {
      // Deprecated
      this.deprecations.onProcessOptions(key, options, '');
      options[key] = {
        ...deprecatedSearchBarOptions,
        visible: value
      };
    } else {
      options[key] = {
        ...deprecatedSearchBarOptions,
        ...value
      };
    }
  }
  processInterpolation(key, value, options) {
    if (isEqual(key, 'interpolation')) {
      if (typeof value === 'string') {
        this.deprecations.onProcessOptions(key, options, '');
        options[key] = {
          type: options[key]
        };
      }
    }
  }
  processAnimation(key, value, options) {
    this.processSetRootAnimation(key, value, options);
    this.processPush(key, value, options);
    this.processPop(key, value, options);
    this.processSetStackRoot(key, value, options);
    this.processShowModal(key, value, options);
    this.processDismissModal(key, value, options);
  }
  processSetStackRoot(key, animation, parentOptions) {
    if (key !== 'setStackRoot') return;
    if (this.isNewStackAnimationApi(animation)) return;
    this.convertDeprecatedViewAnimationApiToNewStackAnimationApi(animation, parentOptions);
  }
  isNewStackAnimationApi(animation) {
    return has(animation, 'content') || has(animation, 'topBar') || has(animation, 'bottomTabs');
  }
  convertDeprecatedViewAnimationApiToNewStackAnimationApi(animation, parentOptions) {
    if (!has(animation, 'content.enter') && !has(animation, 'content.exit')) {
      parentOptions.setStackRoot = {
        content: {
          enter: animation
        }
      };
      if (has(animation, 'enabled')) {
        parentOptions.setStackRoot.enabled = animation.enabled;
      }
      if (has(animation, 'waitForRender')) {
        parentOptions.setStackRoot.waitForRender = animation.waitForRender;
      }
    }
  }
  processPop(key, animation, parentOptions) {
    if (key !== 'pop') return;
    if (animation.content && !has(animation, 'content.enter') && !has(animation, 'content.exit')) {
      parentOptions.pop.content = {
        exit: animation.content
      };
    }
    if (animation.topBar && !has(animation, 'topBar.enter') && !has(animation, 'topBar.exit')) {
      parentOptions.pop.topBar = {
        exit: animation.topBar
      };
    }
    if (animation.bottomTabs && !has(animation, 'bottomTabs.enter') && !has(animation, 'bottomTabs.exit')) {
      parentOptions.pop.bottomTabs = {
        exit: animation.bottomTabs
      };
    }
  }
  processSetRootAnimation(key, animation, parentOptions) {
    if (key !== 'setRoot') return;
    if (Platform.OS === 'android' && !('enter' in animation)) {
      parentOptions.setRoot = {
        enter: animation
      };
    } else if (Platform.OS === 'ios' && 'enter' in animation) {
      parentOptions.setRoot = animation;
    }
  }
  processShowModal(key, animation, parentOptions) {
    if (key !== 'showModal') return;
    if (!('enter' in animation)) {
      const elementTransitions = animation.elementTransitions;
      const sharedElementTransitions = animation.sharedElementTransitions;
      const enter = {
        ...animation
      };
      delete enter.sharedElementTransitions;
      delete enter.elementTransitions;
      parentOptions.showModal = {
        enter,
        sharedElementTransitions,
        elementTransitions
      };
    }
  }
  processDismissModal(key, animation, parentOptions) {
    if (key !== 'dismissModal') return;
    if (!('exit' in animation)) {
      const elementTransitions = animation.elementTransitions;
      const sharedElementTransitions = animation.sharedElementTransitions;
      const exit = {
        ...animation
      };
      delete exit.sharedElementTransitions;
      delete exit.elementTransitions;
      parentOptions.dismissModal = {
        exit,
        sharedElementTransitions,
        elementTransitions
      };
    }
  }
  processPush(key, animation, parentOptions) {
    if (key !== 'push') return;
    if (animation.content && !has(animation, 'content.enter') && !has(animation, 'content.exit')) {
      parentOptions.push.content = {
        enter: animation.content
      };
    }
    if (animation.topBar && !has(animation, 'topBar.enter') && !has(animation, 'topBar.exit')) {
      parentOptions.push.topBar = {
        enter: animation.topBar
      };
    }
    if (animation.statusBar && !has(animation, 'statusBar.enter') && !has(animation, 'statusBar.exit')) {
      parentOptions.push.statusBar = {
        enter: animation.statusBar
      };
    }
    if (animation.bottomTabs && !has(animation, 'bottomTabs.enter') && !has(animation, 'bottomTabs.exit')) {
      parentOptions.push.bottomTabs = {
        enter: animation.bottomTabs
      };
    }
  }
}
//# sourceMappingURL=OptionsProcessor.js.map