/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

import { euiCanAnimate, euiCantAnimate } from '@elastic/eui-theme-common';
import { useEuiTheme } from '../../services/theme';
import { transparentize } from '../../services/color';
import { logicalCSS, logicalCSSWithFallback } from '../functions';

/**
 * Set scroll bar appearance on Chrome (and firefox).
 * All parameters are optional and default to specific global settings.
 */

export var euiScrollBarStyles = function euiScrollBarStyles(_ref) {
  var _ref$euiTheme = _ref.euiTheme,
    colors = _ref$euiTheme.colors,
    size = _ref$euiTheme.size;
  var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    _thumbColor = _ref2.thumbColor,
    _ref2$trackColor = _ref2.trackColor,
    trackColor = _ref2$trackColor === void 0 ? 'transparent' : _ref2$trackColor,
    _ref2$width = _ref2.width,
    width = _ref2$width === void 0 ? 'thin' : _ref2$width,
    _size = _ref2.size,
    _corner = _ref2.corner;
  // Set defaults from theme
  var thumbColor = _thumbColor || transparentize(colors.darkShade, 0.5);
  var scrollBarSize = _size || size.base;
  var scrollBarCorner = _corner || width === 'thin' ? "calc(".concat(size.s, " * 0.75)") : size.xs;

  // Firefox's scrollbar coloring cascades, but the sizing does not,
  // so it's being added to this mixin for allowing support wherever custom scrollbars are
  var firefoxSupport = "scrollbar-color: ".concat(thumbColor, " ").concat(trackColor, ";");
  return "scrollbar-width: ".concat(width, ";\n\n    &::-webkit-scrollbar {\n      ").concat(logicalCSS('width', scrollBarSize), "\n      ").concat(logicalCSS('height', scrollBarSize), "\n    }\n\n    &::-webkit-scrollbar-thumb {\n      background-color: ").concat(thumbColor, ";\n      background-clip: content-box;\n      border-radius: ").concat(scrollBarSize, ";\n      border: ").concat(scrollBarCorner, " solid ").concat(trackColor, ";\n    }\n\n    &::-webkit-scrollbar-corner,\n    &::-webkit-scrollbar-track {\n      background-color: ").concat(trackColor, ";\n    }\n\n    ").concat(firefoxSupport, "\n  ");
};
export var useEuiScrollBar = function useEuiScrollBar(options) {
  var euiTheme = useEuiTheme();
  return euiScrollBarStyles(euiTheme, options);
};

/**
 * *INTERNAL*
 * Overflow shadow masks for use in YScroll and XScroll helpers
 */

export var euiOverflowShadowStyles = function euiOverflowShadowStyles(_ref3) {
  var _ref3$euiTheme = _ref3.euiTheme,
    size = _ref3$euiTheme.size,
    colors = _ref3$euiTheme.colors;
  var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    _direction = _ref4.direction,
    _side = _ref4.side,
    _ref4$hasAnimatedOver = _ref4.hasAnimatedOverflowShadow,
    hasAnimatedOverflowShadow = _ref4$hasAnimatedOver === void 0 ? false : _ref4$hasAnimatedOver;
  var direction = _direction || 'y';
  var side = _side || 'both';
  var hideHeight = size.s;
  var gradientStart = "\n  ".concat(transparentize('red', 0.1), " 0%,\n  ").concat(transparentize('red', 1), " ").concat(hideHeight, "\n  ");
  var gradientEnd = "\n  ".concat(transparentize('red', 1), " calc(100% - ").concat(hideHeight, "),\n  ").concat(transparentize('red', 0.1), " 100%\n  ");
  var gradient = '';
  if (side) {
    if (side === 'both') {
      gradient = "".concat(gradientStart, ", ").concat(gradientEnd);
    } else if (side === 'start') {
      gradient = "".concat(gradientStart);
    } else {
      gradient = "".concat(gradientEnd);
    }
  }

  // Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working
  // This workaround forces a stacking context on the scrolling container, which
  // hopefully addresses the bug. @see:
  // - https://issues.chromium.org/issues/40778541
  // - https://github.com/elastic/kibana/issues/180828
  // - https://github.com/elastic/eui/pull/6343#issuecomment-1302732021
  var chromiumMaskWorkaround = 'transform: translateZ(0);';
  var overflowShadowStatic = direction === 'y' ? "mask-image: linear-gradient(to bottom, ".concat(gradient, "); ").concat(chromiumMaskWorkaround) : "mask-image: linear-gradient(to right, ".concat(gradient, "); ").concat(chromiumMaskWorkaround);

  // If supported, use the scroll timeline API to animate the gradient to show/hide it on the scroll edges.
  // We only support vertical scrolling as horizontal scrolling has increased complexity on element dimensions.
  if (hasAnimatedOverflowShadow && direction === 'y') {
    var featureFlag = 'animation-timeline: scroll()';
    var gradientStartColor = "var(--euiOverflowShadowColor, ".concat(colors.backgroundBasePlain, ")");
    var gradientEndColor = 'transparent';
    var gradientSize = size.base;
    var gradientScrollRange = size.m;
    var commonPseudoElementStyles = "\n      content: '';\n      display: block;\n      position: sticky;\n      z-index: 1;\n      block-size: ".concat(gradientSize, ";\n      pointer-events: none;\n    ");
    return "\n      @supports not (".concat(featureFlag, ") {\n        ").concat(overflowShadowStatic, "\n      }\n\n      ").concat(euiCantAnimate, " {\n        ").concat(overflowShadowStatic, "\n      }\n\n      ").concat(euiCanAnimate, " {\n        @supports (").concat(featureFlag, ") {\n          @keyframes show { \n            from { opacity: 0 } \n            to { opacity: 1 }\n          }\n          @keyframes hide { \n            from { opacity: 1 }\n            to { opacity: 0 }\n          }\n\n          position: relative;\n\n          /* Gradient on start edge */\n          &::before {\n            ").concat(commonPseudoElementStyles, "\n            inset-block-start: 0;\n            /* prevent pushing down the content */\n            ").concat(logicalCSS('margin-bottom', "-".concat(gradientSize)), " \n            /* uses CSS custom property to support customization depending on layout wrapper background color */\n            background: linear-gradient(to bottom, ").concat(gradientStartColor, ", ").concat(gradientEndColor, ");\n            \n            opacity: 0;\n            animation: show linear both;\n            animation-timeline: scroll(y);\n            animation-range: 0px ").concat(gradientScrollRange, ";\n          }\n\n          /* Gradient on end edge */\n          &::after {\n            ").concat(commonPseudoElementStyles, "\n            inset-block-end: 0;\n            /* prevent adding extra space */\n            ").concat(logicalCSS('margin-top', "-".concat(gradientSize)), " \n            background: linear-gradient(to top, ").concat(gradientStartColor, ", ").concat(gradientEndColor, ");\n\n            \n            /* NOTE: To ensure the bottom gradient is not visible when the container has no overflow,\n            we need to use opacity: 0 as default. Using two animations with 'animation-fill-mode: forwards'\n            ensures the show/hide animation works both with and without overflow. */\n            /* scroll animation */\n            opacity: 0;\n            animation-name: show, hide;\n            animation-timing-function: step-start, linear;\n            animation-fill-mode: forwards;\n            animation-timeline: scroll(y);\n            animation-range: 0% 100%, calc(100% - ").concat(gradientScrollRange, ") 100%;\n          }\n        }\n      }\n    ");
  }
  return overflowShadowStatic;
};

/**
 * 1. Focus rings shouldn't be visible on scrollable regions, but a11y requires them to be focusable.
 *    Browser's supporting `:focus-visible` will still show outline on keyboard focus only.
 *    Others like Safari, won't show anything at all.
 */

export var euiYScroll = function euiYScroll(euiTheme) {
  var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    height = _ref5.height;
  return "\n  ".concat(euiScrollBarStyles(euiTheme), "\n  ").concat(logicalCSS('height', height || '100%'), "\n  ").concat(logicalCSSWithFallback('overflow-y', 'auto'), "\n  ").concat(logicalCSSWithFallback('overflow-x', 'hidden'), "\n  &:focus {\n    outline: none; /* 1 */\n  }\n");
};
export var useEuiYScroll = function useEuiYScroll() {
  var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
    height = _ref6.height;
  var euiTheme = useEuiTheme();
  return euiYScroll(euiTheme, {
    height: height
  });
};
export var euiYScrollWithShadows = function euiYScrollWithShadows(euiTheme) {
  var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    height = _ref7.height,
    _ref7$side = _ref7.side,
    side = _ref7$side === void 0 ? 'both' : _ref7$side,
    _ref7$hasAnimatedOver = _ref7.hasAnimatedOverflowShadow,
    hasAnimatedOverflowShadow = _ref7$hasAnimatedOver === void 0 ? false : _ref7$hasAnimatedOver;
  return "\n  ".concat(euiYScroll(euiTheme, {
    height: height
  }), "\n  ").concat(euiOverflowShadowStyles(euiTheme, {
    direction: 'y',
    side: side,
    hasAnimatedOverflowShadow: hasAnimatedOverflowShadow
  }), "\n");
};
export var useEuiYScrollWithShadows = function useEuiYScrollWithShadows() {
  var _ref8 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
    height = _ref8.height,
    side = _ref8.side,
    hasAnimatedOverflowShadow = _ref8.hasAnimatedOverflowShadow;
  var euiTheme = useEuiTheme();
  return euiYScrollWithShadows(euiTheme, {
    height: height,
    side: side,
    hasAnimatedOverflowShadow: hasAnimatedOverflowShadow
  });
};
export var euiXScroll = function euiXScroll(euiTheme) {
  return "\n  ".concat(euiScrollBarStyles(euiTheme), "\n  ").concat(logicalCSSWithFallback('overflow-x', 'auto'), "\n  &:focus {\n    outline: none; /* 1 */\n  }\n");
};
export var useEuiXScroll = function useEuiXScroll() {
  var euiTheme = useEuiTheme();
  return euiXScroll(euiTheme);
};
export var euiXScrollWithShadows = function euiXScrollWithShadows(euiTheme) {
  return "\n  ".concat(euiXScroll(euiTheme), "\n  ").concat(euiOverflowShadowStyles(euiTheme, {
    direction: 'x'
  }), "\n");
};
export var useEuiXScrollWithShadows = function useEuiXScrollWithShadows() {
  var euiTheme = useEuiTheme();
  return euiXScrollWithShadows(euiTheme);
};
export var euiOverflowScroll = function euiOverflowScroll(euiTheme) {
  var _ref9 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    direction = _ref9.direction,
    _ref9$mask = _ref9.mask,
    mask = _ref9$mask === void 0 ? false : _ref9$mask;
  switch (direction) {
    case 'y':
      return mask ? euiYScrollWithShadows(euiTheme) : euiYScroll(euiTheme);
    case 'x':
      return mask ? euiXScrollWithShadows(euiTheme) : euiXScroll(euiTheme);
    default:
      console.warn('Please provide a valid direction option to useEuiOverflowScroll');
      return '';
  }
};
export var useEuiOverflowScroll = function useEuiOverflowScroll(direction) {
  var mask = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  var euiTheme = useEuiTheme();
  return euiOverflowScroll(euiTheme, {
    direction: direction,
    mask: mask
  });
};

/**
 * For quickly applying a full-height element whether using flex or not
 */
export var euiFullHeight = function euiFullHeight() {
  return "\n  ".concat(logicalCSS('height', '100%'), "\n  flex: 1 1 auto;\n  overflow: hidden;\n");
};