import { get as lodashGet } from 'lodash';
import { getStyledObject } from './getStyledComponentAndObjects'; // import { theme as defaultTheme } from '../theme';

const defaultTheme = {};
import { pseudoPropsMap } from '../hooks/useThemeProps/propsFlattener';
import { forEach, map, merge } from 'lodash';
import { isEmptyObj } from '../utils/isEmptyObj'; // Adding Map for storing the props and style for the styled component

export let resolvedStyledMap = {};
export const PSEUDO_PROP_COMPONENT_MAP = {
  _spinner: 'Spinner',
  _stack: 'Stack',
  _text: 'Text',
  _icon: 'Icon',
  _checkbox: 'Checkbox',
  _radio: 'Radio',
  _pressable: 'Pressable',
  _slide: 'Slide',
  _fade: 'Fade',
  _backdropFade: 'BackdropFace'
};
export const COLOR_SCHEME_MAP = {
  Button: true,
  ButtonGroup: true,
  IconButton: true,
  Checkbox: true,
  Radio: true,
  Alert: true,
  Badge: true,
  CircularProgress: true,
  Fab: true,
  Modal: true,
  Progress: true,
  Switch: true,
  Tag: true,
  Slider: true,
  SliderThumb: true,
  // SliderTrack: true,
  SliderFilledTrack: true
};
export const init = inputResolvedStyledMap => {
  if (inputResolvedStyledMap) {
    resolvedStyledMap = inputResolvedStyledMap;
  }

  if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') {
    //@ts-ignore
    window['resolvedStyledMap'] = resolvedStyledMap; //@ts-ignore
  }
};
export const getResolvedStyleMap = (providerId, key) => {
  return resolvedStyledMap[providerId][key];
};
export const setResolvedStyleMap = (providerId, key, value, colorMode) => {
  if (!resolvedStyledMap[providerId]) {
    resolvedStyledMap[providerId] = {};
  }

  const styledMap = resolvedStyledMap[providerId][key];

  if (!styledMap) {
    resolvedStyledMap[providerId][key] = {
      [colorMode]: [value]
    };
  } else {
    if (!styledMap[colorMode]) {
      styledMap[colorMode] = [];
    }

    styledMap[colorMode].push(value);
  }
};
/**
 *
 * @param styleSheet StyleSheet with theme style or state style
 * @param styleSheetProperty key of styleSheet
 * @returns style with current stylsheet property
 */

const getAndMergeThemeFromStylesheet = (styleSheet, styleSheetProperty) => {
  // get style from stylsheet
  const currentPropertyStyleArray = map(styleSheet, styleSheetProperty); // merge styles

  let currentPropertyStyle = {};

  for (const props of currentPropertyStyleArray) {
    currentPropertyStyle = merge({}, currentPropertyStyle, props);
  }

  return currentPropertyStyle;
};

const getThemeObject = (providerId, componentName, colorMode, state) => {
  var _resolvedStyledMap, _resolvedStyledMap$pr;

  const styleObj = (_resolvedStyledMap = resolvedStyledMap) === null || _resolvedStyledMap === void 0 ? void 0 : (_resolvedStyledMap$pr = _resolvedStyledMap[providerId]) === null || _resolvedStyledMap$pr === void 0 ? void 0 : _resolvedStyledMap$pr[componentName];

  if (!styleObj || !styleObj[colorMode]) {
    return {};
  } // Theme style


  let styleSheet = styleObj[colorMode]; // state style

  const stateStyles = getPseudoStateStyles(providerId, componentName, state);

  if (componentName === 'Checkbox' && state.isInvalid && state.isHovered) {// console.log(componentName, stateStyles, 'component state');
  }

  let stateStyleSheet = [];
  forEach(stateStyles, stateStyleObj => {
    if (stateStyleObj[colorMode]) {
      // styleSheet = styleSheet.concat(stateStyleObj[colorMode]);
      stateStyleSheet = stateStyleSheet.concat(stateStyleObj[colorMode]);
    }
  }); // Theme style props resolution

  let unResolvedProps = getAndMergeThemeFromStylesheet(styleSheet, 'unResolvedProps');
  const restDefaultProps = getAndMergeThemeFromStylesheet(styleSheet, 'restDefaultProps');
  const stateRestDefaultProps = getAndMergeThemeFromStylesheet(stateStyleSheet, 'restDefaultProps');
  const styleFromProps = getAndMergeThemeFromStylesheet(styleSheet, 'styleFromProps');
  let internalPseudoProps = getAndMergeThemeFromStylesheet(styleSheet, 'internalPseudoProps'); // State style props resolution

  const stateStyleFromProps = getAndMergeThemeFromStylesheet(stateStyleSheet, 'styleFromProps'); // Merging state styles internal pseudo props with theme style internal pseudo props

  internalPseudoProps = { ...internalPseudoProps,
    ...getAndMergeThemeFromStylesheet(stateStyleSheet, 'internalPseudoProps')
  }; // Merging state styles unresolved props with theme style unresolved props

  unResolvedProps = { ...unResolvedProps,
    ...getAndMergeThemeFromStylesheet(stateStyleSheet, 'unResolvedProps')
  };
  return {
    // style: map(styleSheet, 'style'),
    unResolvedProps: unResolvedProps,
    styleFromProps: styleFromProps,
    stateStyleFromProps: stateStyleFromProps,
    restDefaultProps: restDefaultProps,
    stateRestDefaultProps: stateRestDefaultProps,
    internalPseudoProps: internalPseudoProps
  };
};

const getComponentNameKeyFromProps = (componentName, {
  variant,
  colorScheme
} = {}) => {
  let componentKeyName = componentName; // const componentTheme = lodashGet(theme, `components.${componentName}`, {});

  const colorSchemeKey = colorScheme; // || componentTheme.defaultProps?.colorScheme;

  const variantKey = variant; // || componentTheme.defaultProps?.variant;

  if (colorSchemeKey && variantKey) {
    componentKeyName = "".concat(componentName, ".").concat(colorSchemeKey, ".").concat(variantKey);
  } else if (variantKey) {
    componentKeyName = "".concat(componentName, ".").concat(variant);
  } else if (colorSchemeKey) {
    componentKeyName = "".concat(componentName, ".").concat(colorSchemeKey);
  }

  return componentKeyName;
}; // const get


export const getThemeProps = (theme, providerId, inputComponentKeyName, config, state, props = {}) => {
  const componentNames = inputComponentKeyName.split('.');
  const rootComponentName = componentNames[0];
  const pseudoComponentKeyName = componentNames[1];
  let componentKeyName = rootComponentName;
  componentKeyName = getComponentNameKeyFromProps(rootComponentName, props);

  if (pseudoComponentKeyName) {
    componentKeyName = "".concat(componentKeyName, ".").concat(pseudoComponentKeyName);
  }

  let themeObj = getThemeObject(providerId, componentKeyName, config.colorMode, state);

  if (isEmptyObj(themeObj)) {
    updateComponentThemeMap(theme, providerId, inputComponentKeyName, {}, config, {
      variant: props.variant,
      colorScheme: props.colorScheme
    });
    themeObj = getThemeObject(providerId, componentKeyName, config.colorMode, state);
  }

  if (!isEmptyObj(themeObj) && props.size) {
    let componentKeyNameForSize = "".concat(rootComponentName, ".").concat(props.size);

    if (pseudoComponentKeyName) {
      componentKeyNameForSize = "".concat(componentKeyNameForSize, ".").concat(pseudoComponentKeyName);
    }

    let sizeThemeObj = getThemeObject(providerId, "".concat(componentKeyNameForSize), config.colorMode, state);

    if (isEmptyObj(sizeThemeObj)) {
      if (!pseudoComponentKeyName) {
        if (isEmptyObj(sizeThemeObj)) {
          updateComponentThemeMap(theme, providerId, rootComponentName, {}, config, {
            size: props.size
          });
          sizeThemeObj = getThemeObject(providerId, componentKeyNameForSize, config.colorMode, state);
        }
      }
    }

    const mergedThemeObj = {
      // style: sizeThemeObj?.style
      //   ? [...themeObj?.style, ...sizeThemeObj?.style]
      //   : themeObj.style,
      styleFromProps: merge({}, themeObj.styleFromProps, sizeThemeObj.styleFromProps),
      unResolvedProps: merge({}, themeObj.unResolvedProps, sizeThemeObj.unResolvedProps),
      internalPseudoProps: merge({}, themeObj.internalPseudoProps, sizeThemeObj.internalPseudoProps),
      stateStyleFromProps: merge({}, themeObj.stateStyleFromProps, sizeThemeObj.stateStyleFromProps),
      restDefaultProps: { ...themeObj.restDefaultProps,
        ...sizeThemeObj.restDefaultProps
      },
      stateRestDefaultProps: { ...themeObj.stateRestDefaultProps,
        ...sizeThemeObj.stateRestDefaultProps
      }
    };
    themeObj = mergedThemeObj;
  }

  return themeObj;
};
export const getResolvedProps = (key, colorMode) => {
  const styleObj = resolvedStyledMap[key];

  if (!colorMode || !styleObj) {
    return null;
  }

  return styleObj[colorMode]['styleFromProps'];
};

const isValidStateKey = (stateKey, state) => {
  // console.log(stateKey, pseudoPropStateMap[stateKey], state, 'is valid');
  try {
    //@ts-ignore
    return state[pseudoPropsMap[stateKey].respondTo];
  } catch (e) {
    return false;
  }
};

const isValidState = (key, state) => {
  // include only startWith("_")
  const stateKeys = key.split('.');
  const isValid = stateKeys.every(stateKey => {
    if (isValidStateKey(stateKey, state)) {
      return true;
    }

    return false;
  }); // console.log(isValid, 'valid here');

  return isValid;
};

const getPriority = propName => {
  const propNameArray = propName.split('.');
  const maxPriority = propNameArray.reduce((previousValue, currentValue) => {
    var _pseudoPropsMap$curre;

    //@ts-ignore
    return Math.max(previousValue, (_pseudoPropsMap$curre = pseudoPropsMap[currentValue]) === null || _pseudoPropsMap$curre === void 0 ? void 0 : _pseudoPropsMap$curre.priority);
  }, 0);
  const priority = //@ts-ignore
  maxPriority + propNameArray.length / 10; // }

  return priority;
};

const getPseudoStateStyles = (providerId, componentName, state) => {
  const styleObj = [];
  const stateStyleArray = [];
  const componentStates = getResolvedStyleMap(providerId, componentName); // console.log(componentStates, '***** &&&&');
  // const currentPriority = 0;

  for (const k in componentStates) {
    const value = componentStates[k]; // console.log(componentStates, k, componentName, 'value **&');
    //get for _hover, _checked

    if (k.startsWith('_')) {
      const priority = getPriority(k);
      stateStyleArray.push({
        key: k,
        value: value,
        priority: priority
      });
    }
  }

  stateStyleArray.sort((obj1, obj2) => obj1.priority - obj2.priority);
  stateStyleArray.forEach(item => {
    if (isValidState(item.key, state)) {
      styleObj.push(item.value);
    }
  });
  return styleObj;
};

const resolveForInternalPseudoProps = (theme, providerId, name, key, styledObj, config, mergeDefaultProps = true, propertyName) => {
  // if (name !== 'Button') {
  //   return;
  // }
  for (const property in styledObj.internalPseudoProps) {
    if (PSEUDO_PROP_COMPONENT_MAP[property]) {
      //TODO: not calling again for nested state prop
      if (!propertyName) {
        updateComponentThemeMapForColorMode(theme, providerId, PSEUDO_PROP_COMPONENT_MAP[property], "".concat(key, ".").concat(PSEUDO_PROP_COMPONENT_MAP[property]), styledObj.internalPseudoProps[property], config, false, mergeDefaultProps);
      }
    } else {
      // const themeProps = getThemeProps(name, colorMode, {
      //   [pseudoPropStateMap[property]]: true,
      // });
      // if (property === '_hover') {
      //   console.log(
      //     // name,
      //     // property,
      //     // pseudoPropStateMap[property],
      //     themeProps,
      //     {
      //       ...themeProps.styleFromProps,
      //       ...styledObj.internalPseudoProps[property],
      //     },
      //     'theme props '
      //   );
      // }
      // console.log(name, key, 'config here');
      const styledObjNestedProp = getStyledObject(theme, name, {}, config, styledObj.internalPseudoProps[property]);
      const componentMapPath = key;
      const componentObj = getResolvedStyleMap(providerId, componentMapPath);

      if (componentObj) {
        var _pseudoPropsMap$prope;

        // const stateKey = key.slice(componentMapPath.length + 1);
        //@ts-ignore
        if (pseudoPropsMap !== null && pseudoPropsMap !== void 0 && (_pseudoPropsMap$prope = pseudoPropsMap[property]) !== null && _pseudoPropsMap$prope !== void 0 && _pseudoPropsMap$prope.respondTo) {
          const stateKey = propertyName ? propertyName + '.' + property : property;

          if (componentObj[stateKey]) {
            if (!componentObj[stateKey][config.colorMode]) {
              componentObj[stateKey][config.colorMode] = [];
            }

            componentObj[stateKey][config.colorMode].push(styledObjNestedProp);
          } else {
            componentObj[stateKey] = {
              [config.colorMode]: [styledObjNestedProp]
            };
          } // if (name == 'Checkbox') {
          //   console.log(
          //     // property,
          //     key,
          //     // componentObj,
          //     // componentMapPath,
          //     styledObjNestedProp,
          //     'hello here 111'
          //   );
          // if (!isEmptyObj(styledObjNestedProp.internalPseudoProps)) {


          resolveForInternalPseudoProps(theme, providerId, name, key, styledObjNestedProp, config, false, property); // }
          // }
        } else {
          // console.log(
          //   'hello here &&&*',
          //   styledObj.internalPseudoProps[property]
          // );
          if (!propertyName) {
            componentObj[config.colorMode][0].unResolvedProps = { ...componentObj[config.colorMode][0].unResolvedProps,
              [property]: styledObj.internalPseudoProps[property]
            };
          } else {
            componentObj[propertyName][config.colorMode][0].unResolvedProps = { ...componentObj[propertyName][config.colorMode][0].unResolvedProps,
              [property]: styledObj.internalPseudoProps[property]
            };
          }
        }
      }
    }
  }
};

export const updateComponentThemeMapForColorMode = (theme, providerId, name, key, inputProps, config = {
  colorMode: 'light',
  platform: 'web'
}, resolveForStatePseudoProps = false, mergeDefaultProps = true) => {
  // console.log(theme, 'theme here');
  let componentTheme = lodashGet(theme, "components.".concat(name), {}); // let componentTheme = get(defaultTheme, `components.${name}`, {});
  // if (runtime) {
  //   componentTheme =
  // }
  // resolve for variant

  if (resolveForStatePseudoProps) {
    componentTheme = {};
  }

  const styledObj = getStyledObject(theme, name, componentTheme, config, { ...inputProps,
    extraProp: key
  }, mergeDefaultProps);
  setResolvedStyleMap(providerId, key, styledObj, config.colorMode); // console.log(key, styledObj, config.colorMode, '&&&&&&');

  resolveForInternalPseudoProps(theme, providerId, name, key, styledObj, config, mergeDefaultProps);
  return styledObj;
}; // export const resolveDefaultTheme = (platform?: string) => {
//   // for (const key in theme.components) {
//   //   // console.log(key, platform);
//   //   updateComponentThemeMap(key, {}, { platform });
//   // }
//   // return resolvedStyledMap;
// };

export const generateBuildTimeMap = (platform = 'web', usedComponentDetailMap) => {
  const componentsUsed = Object.keys(usedComponentDetailMap);

  for (const componentName of componentsUsed) {
    const componentPropsArray = usedComponentDetailMap[componentName];

    for (const componentProps of componentPropsArray) {
      updateComponentThemeMap(defaultTheme, // boot time provider id
      'generatedBuildTimeMap', componentName, {}, {
        platform,
        colorMode: 'light'
      }, componentProps);
      updateComponentThemeMap(defaultTheme, // boot time provider id
      'generatedBuildTimeMap', componentName, {}, {
        platform,
        colorMode: 'dark'
      }, componentProps);
    }
  } // return resolvedStyledMap;

};
export const updateComponentThemeMap = (theme, providerId, name, inputProps, config = {
  platform: 'web',
  colorMode: 'light'
}, props) => {
  const {
    platform,
    colorMode
  } = config; // console.log(props, 'props here');
  // const componentTheme = get(theme, `components.${name}`, {});

  let themeObj = {}; // if (runTimeResolution) {

  const currentColorScheme = props === null || props === void 0 ? void 0 : props.colorScheme; // || componentTheme?.defaultProps?.colorScheme;

  const currentVariant = props === null || props === void 0 ? void 0 : props.variant; // || componentTheme?.defaultProps?.variant;

  const currentSize = props === null || props === void 0 ? void 0 : props.size; // || componentTheme?.defaultProps?.size;

  if (currentVariant && currentColorScheme) {
    themeObj = updateComponentThemeMapForColorMode(theme, providerId, name, "".concat(name, ".").concat(currentColorScheme, ".").concat(currentVariant), {
      variant: currentVariant,
      colorScheme: currentColorScheme
    }, {
      colorMode,
      platform
    });
  } else if (currentColorScheme) {
    // if (name === 'SliderThumb') {
    //   console.log(props, 'hello slider ');
    // }
    themeObj = updateComponentThemeMapForColorMode(theme, providerId, name, "".concat(name, ".").concat(currentColorScheme), {
      colorScheme: currentColorScheme
    }, {
      colorMode,
      platform
    });
  } else if (currentVariant) {
    themeObj = updateComponentThemeMapForColorMode(theme, providerId, name, "".concat(name, ".").concat(currentVariant), {
      variant: currentVariant
    }, {
      colorMode,
      platform
    });
  } else if (currentSize) {
    // console.log(name, 'name here 111', currentSize);
    // if (name == 'Button') {
    //   console.trace('hh');
    // }
    themeObj = updateComponentThemeMapForColorMode(theme, providerId, name, "".concat(name, ".").concat(currentSize), {
      size: currentSize
    }, {
      colorMode,
      platform
    }, false, false);
  } else {
    themeObj = updateComponentThemeMapForColorMode(theme, providerId, name, name, inputProps, {
      colorMode,
      platform
    }, false, true);
  }

  return themeObj;
};
//# sourceMappingURL=styled.js.map