import React from 'react';
import { StyleSheet } from 'react-native';
import { Defs, G, LinearGradient, Path, Stop, Svg } from 'react-native-svg';
import { SBox } from '../../common/s-components/layout/s-box';
import { SText } from '../../common/s-components/typography/s-text';
import { AngleGradient } from '../../common/components/angle-gradient';
import { formatStream } from '../../common/transducers';
import { fp as _ } from '../../common/utils/fp';
import {
  getArcBoldPathGenerator,
  getArcBoldPathGeneratorSmall,
  getArcThinPathGenerator,
  getArcThinPathGeneratorSmall,
  getDonutParameters,
  getSemidonutSections,
  getSemidonutSectionsRight,
} from '../transducers';
import { TColors, TSegments } from '../types';

// https://stackoverflow.com/questions/48280641/label-for-d3-Semidonut-chart

/*
 * https://github.com/d3/d3-shape?source=post_page---------------------------#arcs
 *
 *  Issue with conical gradient in svg
 * https://stackoverflow.com/a/18210763/6190198
 * http://bl.ocks.org/bycoffe/18441cddeb8fe147b719fab5e30b5d45
 * https://stackoverflow.com/questions/18198252/d3-arc-gradient
 * https://bl.ocks.org/tomshanley/9953da50ec833fdb4819dd065d2f6643
 *
 * About labels centering
 * http://jsfiddle.net/Orbifold/nnm6kg4m/
 * https://bl.ocks.org/laxmikanta415/dc33fe11344bf5568918ba690743e06f
 * https://www.d3-graph-gallery.com/graph/donut_label.html
 * */

type TProps = {
  segments: TSegments;
  colors: TColors;
  direction?: string;
  total?: number;
  variant?: 'small';
};

export const Semidonut: React.FC<TProps> = props => {
  const { segments, colors, total, direction, variant } = props;
  const sectionAngles =
    direction === 'left'
      ? getSemidonutSections(segments)
      : getSemidonutSectionsRight(segments);
  const pathGeneratorBig =
    variant === 'small'
      ? getArcBoldPathGeneratorSmall()
      : getArcBoldPathGenerator();
  const pathGeneratorSmall =
    variant === 'small'
      ? getArcThinPathGeneratorSmall()
      : getArcThinPathGenerator();
  const isSmall = variant === 'small';
  const svgHeight = !isSmall ? 210 : 130;
  const width = !isSmall ? 225 : 146;
  const semiWidth = width / 2;
  const semiHeight = svgHeight / 2;
  const { gradientAngle /*, anchors */ } = getDonutParameters(
    sectionAngles,
    100,
    svgHeight,
    width
  );
  const graphHeight = svgHeight - 12;

  return (
    <SBox position="relative" width={semiWidth - 9}>
      {variant !== 'small' ? (
        <SBox
          style={StyleSheet.absoluteFill}
          display="flex"
          justifyContent="center"
        >
          <SBox>
            <SText
              medium
              fontSize={24}
              letterSpacing={1}
              mt={9}
              textAlign={direction}
            >
              {_.path([0, 'value'], segments).toFixed()}%
            </SText>
            <SText
              semibold
              fontSize={12}
              textAlign={direction}
              mt={3}
              color="white"
              xs
              letterSpacing={1}
            >
              {formatStream(total)}
            </SText>
          </SBox>
        </SBox>
      ) : null}

      <SBox height={graphHeight}>
        <Svg
          width={semiWidth}
          height={svgHeight}
          style={{ transform: [{ translateY: -5 }, { translateX: -3 }] }}
        >
          <Defs>
            {sectionAngles.map(d => {
              const { index } = d;
              // gradient rotation https://codepen.io/NV/pen/jcnmK
              // https://codepen.io/NV/pen/jcnmK
              return (
                <AngleGradient key={index} angle={gradientAngle[index]}>
                  <LinearGradient id={`grad${index}`}>
                    <Stop
                      offset="0"
                      stopColor={_.path(
                        [index, direction === 'left' ? 'start' : 'end'],
                        colors
                      )}
                    />
                    <Stop
                      offset="1"
                      stopColor={_.path(
                        [index, direction === 'left' ? 'end' : 'start'],
                        colors
                      )}
                    />
                  </LinearGradient>
                </AngleGradient>
              );
            })}
          </Defs>
          <G
            transform={
              direction === 'left'
                ? `translate(0, ${semiHeight})`
                : `translate(${semiWidth - 5}, ${semiHeight})`
            }
          >
            {sectionAngles.map((d, index) => {
              return (
                <Path
                  // eslint-disable-next-line
                  key={index}
                  d={
                    index === 0 ? pathGeneratorBig(d)! : pathGeneratorSmall(d)!
                  }
                  fill={`url(#grad${index})`}
                  strokeWidth={1}
                  opacity={index > 0 ? 0.5 : 1}
                />
              );
            })}
          </G>
        </Svg>
      </SBox>
    </SBox>
  );
};

Semidonut.defaultProps = {
  direction: 'left',
};
