"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useResponsiveQuery = void 0;

var _createCompileableStyle = _interopRequireDefault(require("react-native-web/dist/exports/StyleSheet/createCompileableStyle"));

var _i18nStyle = _interopRequireDefault(require("react-native-web/dist/exports/StyleSheet/i18nStyle"));

var _compile = require("react-native-web/dist/exports/StyleSheet/compile");

var _styleResolver = _interopRequireDefault(require("react-native-web/dist/exports/StyleSheet/styleResolver"));

var _reactNative = require("react-native");

var _stableHash = _interopRequireDefault(require("stable-hash"));

var _hash = _interopRequireDefault(require("./hash"));

var _useStableMemo = require("./useStableMemo");

var _common = require("./common");

var _NativeBaseContext = require("../../core/NativeBaseContext");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

//@ts-ignore
//@ts-ignore
//@ts-ignore
//@ts-ignore
//@ts-ignore
// import type { GetResponsiveStylesReturnType } from './types';
// 1. i18nStyle - Does swapping of ltr styles if enabled by user
// 2. createCompileableStyle - Handles shadow/text shadow conversion from RN styles to web styles
// 3. atomic - God function. Pure and memoizes input/output.
// This is a great function, it handles prefixing, converting RN specific styles to web styles and generating the CSS selector
// Input {marginTop: 10}
// Output {"r-margin-top-[hash]-10": {
//   property: "marginTop",
//   value: "10px",
//   identifier: "r-margin-top-[hash]-10",
//   rules: [{`.r-margin-top-[hash]-10: {'margin-top': '10px;`} }]
// }}
// 4. styleResolver - holds the reference of sheet object used to inject CSS. This exposes 2 functions.
// - getTextContent => for ssr style injection
// - insert => for inserting styles in style tag
// If we somehow manage to use these functions, we won't need any extra workarounds for ssr initial style injection or CSS declaration order specifictity
// Here issue is that it internally uses a cache to verify if a css rule is inserted using selector name (class name generated by RN web)
// refer line number 121 in `react-native-web/dist/exports/StyleSheet/createOrdererdCSSStyleSheetfile`.
// We can trick this hash id generator by adding a comment on top of our media query rule in this format. /* media-query + data-attr {} */ then it'll start using media-query + data-attr as cache key
const MEDIA_QUERY_STYLESHEET_GROUP = 3;

const useResponsiveQuery = queries => {
  const isSSR = (0, _NativeBaseContext.useNativeBaseConfig)('NativeBase').isSSR;
  const disableCSSMediaQueries = !isSSR; // Only attaches listener if disableCSSMediaQueries is true

  const windowWidth = (0, _common.useDimensionsWithEnable)({
    enable: disableCSSMediaQueries
  }).width;
  const values = (0, _useStableMemo.useStableMemo)(() => {
    // Use the non-media query responsive styling
    if (disableCSSMediaQueries) {
      const getResponsiveStyles = (0, _common.getResponsiveStylesImpl)(windowWidth);

      if (queries) {
        const {
          styles
        } = getResponsiveStyles(queries);
        return {
          styles,
          getResponsiveStyles
        };
      } else {
        return {
          getResponsiveStyles
        };
      }
    } else {
      if (queries) {
        const {
          styles,
          dataSet
        } = getResponsiveStyles(queries);
        return {
          dataSet,
          styles,
          getResponsiveStyles
        };
      } else {
        return {
          getResponsiveStyles
        };
      }
    }
  }, [queries, windowWidth, disableCSSMediaQueries]);
  return values;
};

exports.useResponsiveQuery = useResponsiveQuery;

const getDataAttribute = queryRule => {
  if (typeof queryRule.minWidth === 'number' && typeof queryRule.maxWidth === 'number') {
    return "min-width-".concat(queryRule.minWidth, "-max-width-").concat(queryRule.maxWidth);
  } else if (typeof queryRule.minWidth === 'number') {
    return "min-width-".concat(queryRule.minWidth);
  } else if (typeof queryRule.maxWidth === 'number') {
    return "max-width-".concat(queryRule.maxWidth);
  }

  return undefined;
};

const getMediaQueryRule = (query, newRule) => {
  if (typeof query.minWidth === 'number' && typeof query.maxWidth === 'number') {
    return "@media only screen and (min-width: ".concat(query.minWidth, "px) and (max-width: ").concat(query.maxWidth, "px) { ").concat(newRule, " }");
  } else if (typeof query.minWidth === 'number') {
    return "@media only screen and (min-width: ".concat(query.minWidth, "px) { ").concat(newRule, " }");
  } else if (typeof query.maxWidth === 'number') {
    return "@media only screen and (max-width: ".concat(query.maxWidth, "px) { ").concat(newRule, " }");
  }

  return undefined;
};

const getResponsiveStyles = queries => {
  const queryString = (0, _stableHash.default)(queries.query);
  const queriesHash = (0, _hash.default)(queryString);
  const styles = queries.initial ? [_reactNative.StyleSheet.create({
    initial: _reactNative.StyleSheet.flatten(queries.initial)
  }).initial] : undefined; // const styleFromQuery = queries.initial ? [queries.initial] : undefined;

  let dataSet = {};

  if (queries.query) {
    queries.query.forEach(queryRule => {
      const queryHash = queriesHash + (0, _hash.default)((0, _stableHash.default)(queryRule));
      const dataAttribute = getDataAttribute(queryRule);

      if (dataAttribute) {
        const newIdentifier = "[data-".concat(dataAttribute, "$=\"").concat(queryHash, "\"]");
        dataSet[dataAttribute] = queryHash;
        let mediaRules = '';

        const flattenQueryStyle = _reactNative.StyleSheet.flatten(queryRule.style);

        const newStyle = (0, _createCompileableStyle.default)((0, _i18nStyle.default)(flattenQueryStyle));
        const results = (0, _compile.atomic)(newStyle);
        Object.keys(results).forEach(key => {
          const oldIdentifier = results[key].identifier;

          if (process.env.NODE_ENV !== 'production') {
            dataSet[dataAttribute] = oldIdentifier + ' ' + dataSet[dataAttribute];
          }

          results[key].rules.forEach(oldRule => {
            // Rule returned by atomic has css selectors, so we'll replace it with data-attr selector
            const newRule = oldRule.replace('.' + oldIdentifier, newIdentifier);
            mediaRules += newRule;
          });
        });

        if (mediaRules) {
          const mediaQueryRule = getMediaQueryRule(queryRule, mediaRules); // Here by prepending the /*${queryHash}{}*/ comment, we're kind of tricking the regex used by rn-web to verify if a rule is inserted or not.
          // Looks safe to me, just need to keep a check if there are any implementation changes in createStyleSheet file in rn-web in future.
          // Second argument defines the order of the insertion. DataSet and class selectors have same CSS specificity so we need to make sure that media rules have higher precedence. Max precendence in RN web is around 2.2 so 3 ensures styles will be appended later

          _styleResolver.default.sheet.insert("/*".concat(queryHash, "{}*/").concat(mediaQueryRule), MEDIA_QUERY_STYLESHEET_GROUP);
        }
      }
    });
  }

  return {
    styles,
    styleFromQuery: _reactNative.StyleSheet.flatten(styles),
    dataSet
  };
};
//# sourceMappingURL=useResponsiveQuery.web.js.map