import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import React, { forwardRef, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { clamp, filter, identity, join, o, path } from 'ramda';
import { Transition } from 'react-transition-group';
import useTheme from '../hooks/useTheme';
import Box from '../Box';
import Text from '../Text';
import { cos, sin } from '../utils/math';
const joinWithDash = o(join('-'), filter(Boolean));

const getCirmcumference = radius => 2 * radius * Math.PI;

const getArcCircumference = C => arcAngle => arcAngle / 360 * C;

const coord = (x, y) => ({
  x,
  y
});

const equalCoord = x => ({
  x,
  y: x
});

const getArcProps = ({
  radius,
  arcAngle
}) => {
  const C = getCirmcumference(radius);
  const CArc = getArcCircumference(C)(arcAngle);
  const offset = C - CArc;
  return {
    CArc,
    C,
    offset
  };
};

export const SvgGradient = (_ref) => {
  let {
    variant
  } = _ref,
      rest = _objectWithoutProperties(_ref, ["variant"]);

  const theme = useTheme();
  const gradient = path(['gauge', variant, 'gradient'].filter(Boolean))(theme);
  return /*#__PURE__*/React.createElement("linearGradient", _extends({
    x1: "0%",
    y1: "0%",
    x2: "100%",
    y2: "0%"
  }, rest), gradient.map(([offset, stopColor]) => /*#__PURE__*/React.createElement("stop", _extends({
    key: `${offset}-${stopColor}`
  }, {
    offset,
    stopColor
  }))));
};
process.env.NODE_ENV !== "production" ? SvgGradient.propTypes = {
  variant: PropTypes.string
} : void 0;
const Gauge = /*#__PURE__*/forwardRef((_ref2, ref) => {
  let {
    arcAngle = 240,
    animationDuration = 1000,
    size = 256,
    rimStrokeWidth = 1,
    gaugeStrokeWidth = 4,
    value = 0,
    valueProps,
    min = 0,
    max = 1,
    format = identity,
    formatLegend = identity,
    title,
    legendProps: legendPropsProp,
    variant
  } = _ref2,
      rest = _objectWithoutProperties(_ref2, ["arcAngle", "animationDuration", "size", "rimStrokeWidth", "gaugeStrokeWidth", "value", "valueProps", "min", "max", "format", "formatLegend", "title", "legendProps", "variant"]);

  // hack to run animation after mount
  const [inProp, setInProp] = useState(false);
  useEffect(() => {
    setInProp(true);
  }, []);
  const svgSize = 32; // Angle between horizontal axis and the start of gauge

  const alpha = (arcAngle - 180) / 2; // Labels needs to be moved a bit

  const alphaLabels = alpha + 10; // We need to move SVG Circle's zero angle
  // so the gauge stroke is visually symmetric.

  const rotateForSymmetryAngle = -alpha - 180; // Normalized value between 0-1

  const valueNormalized = clamp(0, 1)((value - min) / (max - min)); // Coords of center of the canvas

  const center = equalCoord(svgSize / 2);
  const radiusRim = center.x - rimStrokeWidth / 2;
  const radiusGauge = center.x - (rimStrokeWidth + gaugeStrokeWidth / 2);
  const rimProps = getArcProps({
    radius: radiusRim,
    arcAngle
  });
  const gaugeProps = getArcProps({
    radius: radiusGauge,
    arcAngle: arcAngle * valueNormalized
  });
  const circleProps = {
    transform: `rotate(${rotateForSymmetryAngle} ${center.x} ${center.y})`
  };

  const legendProps = _objectSpread({
    fill: '#000000',
    stroke: 'none',
    fontSize: '2px'
  }, legendPropsProp);

  const legend = coord(radiusRim * cos(alphaLabels), radiusRim * sin(alphaLabels));
  const transitionStyles = {
    entering: {
      strokeDashoffset: gaugeProps.offset
    },
    entered: {
      strokeDashoffset: gaugeProps.offset
    },
    exiting: {
      strokeDashoffset: gaugeProps.C
    },
    exited: {
      strokeDashoffset: gaugeProps.C
    }
  };
  const gradientId = joinWithDash(['gradient-arc', variant]);
  return /*#__PURE__*/React.createElement(Box, _extends({
    ref: ref,
    __css: {
      position: 'relative',
      width: `${size}px`,
      height: `${size}px`
    }
  }, rest), /*#__PURE__*/React.createElement(Box, _extends({
    mt: 0,
    mb: 0,
    fontSize: 8,
    __css: {
      whiteSpace: 'nowrap',
      transform: 'translate(-50%, -50%)',
      position: 'absolute',
      left: '50%',
      top: '50%'
    }
  }, valueProps), format(value)), /*#__PURE__*/React.createElement(Box, {
    as: "svg",
    viewBox: `0 0 ${svgSize} ${svgSize}`,
    width: size,
    height: size,
    fill: "none",
    stroke: "currentcolor",
    role: "img",
    "aria-valuenow": value,
    "aria-valuemin": min,
    "aria-valuemax": max,
    __css: {
      color: 'primary'
    }
  }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement(SvgGradient, {
    variant: variant,
    id: gradientId
  })), title && /*#__PURE__*/React.createElement("title", null, title), /*#__PURE__*/React.createElement(Text, _extends({
    variant: "",
    as: "text",
    x: center.x - legend.x,
    y: center.y + legend.y,
    textAnchor: "start"
  }, legendProps), formatLegend(min)), /*#__PURE__*/React.createElement(Text, _extends({
    variant: "",
    as: "text",
    x: center.x + legend.x,
    y: center.y + legend.y,
    textAnchor: "end"
  }, legendProps), formatLegend(max)), /*#__PURE__*/React.createElement("circle", _extends({
    strokeWidth: rimStrokeWidth,
    opacity: 4 / 5,
    cx: center.x,
    cy: center.y,
    r: radiusRim,
    stroke: `url(#${gradientId})`,
    strokeDasharray: rimProps.C,
    strokeDashoffset: rimProps.offset
  }, circleProps)), /*#__PURE__*/React.createElement(Transition, {
    in: inProp,
    timeout: {
      enter: animationDuration,
      exit: animationDuration
    },
    appear: true
  }, state => /*#__PURE__*/React.createElement(Box, _extends({
    as: "circle",
    cx: center.x,
    cy: center.y,
    r: radiusGauge,
    opacity: 1 / 3,
    stroke: `url(#${gradientId})`,
    strokeWidth: gaugeStrokeWidth,
    strokeDasharray: gaugeProps.C,
    __css: {
      transition: `stroke-dashoffset ${animationDuration}ms cubic-bezier(0, 0, 0.2, 1)`
    }
  }, transitionStyles[state], circleProps)))));
});
Gauge.displayName = 'Gauge';
process.env.NODE_ENV !== "production" ? Gauge.propTypes = {
  animationDuration: PropTypes.number,
  arcAngle: PropTypes.number,
  format: PropTypes.func,
  formatLegend: PropTypes.func,
  gaugeStrokeWidth: PropTypes.number,
  legendProps: PropTypes.object,
  max: PropTypes.number,
  min: PropTypes.number,
  rimStrokeWidth: PropTypes.number,
  size: PropTypes.number,
  title: PropTypes.string,
  value: PropTypes.number,
  valueProps: PropTypes.object,
  variant: PropTypes.string
} : void 0;
export default Gauge;