import React, { useCallback, useRef } from 'react';
import { Svg, G } from 'react-native-svg';
import * as d3 from 'd3';
import { Line } from '../../graph/components/line';
import { YAxis } from '../../graph/components/y-axis';
import { XAxis } from '../../graph/components/x-axis';
import { SBox } from '../../common/s-components/layout/s-box';
import { Button } from '../../common/components/button';
import { fp as _ } from '../../common/utils/fp';
import { XAxisLabels } from '../../graph/components/x-axis-labels';
import { YAxisLabels } from '../../graph/components/y-axis-labels';
import { theme } from '../../app/theme';
import { SH3 } from '../../common/s-components/typography/s-h3';
import { SH6 } from '../../common/s-components/typography/s-h6';
import { ShadowBox } from '../../common/components/shadow-box';
import { PORTRAIT_WIDTH, GRAPH_PADDING_TOP_RATIO } from '../../graph/constants';
import { Icon } from '../../common/components/icon';
import { SRow } from '../../common/s-components/layout/s-row';
import { SGradientCard } from '../../common/s-components/s-gradient-card';
import { getWinWidth } from '../../graph/transducers';
import {
  TCoordinates,
  TEntityVisibility,
  TGraphMaxes,
  TIconName,
  TPositionTrend,
  TTrendEntity,
  TVendor,
} from '../../common/types';
import { SText } from '../../common/s-components/typography/s-text';
import { Media } from '../../common/components/media';
import { PositionTrendsLabel } from '../../common/components/position-trends-label';
import { SkeletonsSmall } from '../../common/components/skeleton-small';
import { SLabel } from '../s-components/s-label';
import { SValue } from '../s-components/s-value';
import { SGraphTitle } from '../s-components/s-graph-title';

type TProps = {
  title?: string;
  showTitleIcon?: boolean;
  dotted: TCoordinates;
  maxes?: TGraphMaxes;
  ticks?: number[];
  onFullScreen: () => void;
  variant?: string;
  id: string;
  currentAvg: string;
  trend: TTrendEntity;
  graphVisibility: TEntityVisibility;
  infoVisibility: TEntityVisibility;
  vendor: TVendor;
  sourceName: string;
  lastValue?: string;
  streamsPerListener?: {
    currentAvg: string;
    trend: TTrendEntity;
  };
  streamsPerListenersVisibility: TEntityVisibility;
};

export const LineGraphNew: React.FC<TProps> = props => {
  const { vendor } = props;
  const winWidth = useRef(getWinWidth());

  const getSizes = useCallback(() => {
    const width = vendor === 'spotify' ? PORTRAIT_WIDTH : winWidth.current;
    const padding = 16;
    const paddingTop = vendor === 'spotify' ? 15 : 3;
    const paddingBottom = vendor === 'spotify' ? 61 : 72;
    const containerHeight = vendor === 'spotify' ? 328 : 320;
    const height = vendor === 'spotify' ? 306 : 298;

    const graphHeight = 156;
    const innerHeight = graphHeight - paddingBottom;

    const innerWidth = width;

    return {
      containerHeight,
      graphHeight,
      height,
      width,
      padding,
      paddingTop,
      paddingBottom,
      innerHeight,
      innerWidth,
    };
  }, [vendor, winWidth.current]);

  const getScales = () => {
    // @ts-ignore
    const { innerWidth, padding, paddingTop, innerHeight } = getSizes();
    const {
      // @ts-ignore
      maxes: { xMin, xMax, yMax },
    } = props;

    const xScale = d3
      .scaleLinear()
      .domain([xMin, xMax])
      .range([padding, innerWidth - padding]);
    const yScale = d3
      .scaleLinear()
      .domain([0, yMax])
      .range([innerHeight, paddingTop]);

    return { xScale, yScale };
  };

  const renderStreamsGraphErrorText = () => {
    return (
      <SBox>
        <SH3 medium letterSpacing={1}>
          N/A
        </SH3>
      </SBox>
    );
  };

  const renderStreamsGraphFooterData = (
    value: string,
    trend: TPositionTrend,
    rest: any
  ) => {
    return (
      <>
        <SH3 medium letterSpacing={1}>
          {value}
        </SH3>
        {value !== 'N/A' ? (
          <SBox {...rest}>
            <PositionTrendsLabel
              showPercent
              showZerroTrend
              trend={trend}
              isTransparent
              isReversed
              paddingRight={0}
              paddingLeft={0}
              paddingTop={0}
              paddingBottom={0}
            />
          </SBox>
        ) : null}
      </>
    );
  };

  const renderGraphErrorText = () => {
    return (
      <SBox>
        <SValue medium>N/A</SValue>
      </SBox>
    );
  };

  const renderGraphFooterData = (value: string, trend: TPositionTrend) => {
    return (
      <SRow alignItems="center">
        <SValue medium>{value}</SValue>
        {value !== 'N/A' ? (
          <PositionTrendsLabel
            showPercent
            showZerroTrend
            trend={trend}
            isTransparent
            isReversed
            paddingRight={0}
            paddingLeft={8}
            paddingTop={0}
            paddingBottom={0}
          />
        ) : null}
      </SRow>
    );
  };

  const {
    dotted,
    maxes: { xMin, xMax, yMax } = {},
    ticks,
    onFullScreen,
    title,
    showTitleIcon,
    variant,
    id,
    currentAvg,
    trend,
    graphVisibility,
    infoVisibility,
    sourceName,
    lastValue,
    streamsPerListener,
    streamsPerListenersVisibility,
  } = props;
  // @ts-ignore
  const { containerHeight, height, innerWidth, padding, width } = getSizes();

  const hideGraph = _.any(_.isNil)([yMax, xMax, xMin]);
  let xScale: any;
  let yScale: any;
  let yTicks: any;
  let graphMax: any;

  if (!hideGraph) {
    ({ xScale, yScale } = getScales());
    yTicks = [0, yMax];
    graphMax = yMax! / GRAPH_PADDING_TOP_RATIO;
  }

  const btnWidth = 140;
  const btnLeftPosition = (innerWidth - btnWidth) / 2;
  const skeletonGraphWidth = vendor === 'spotify' ? 250 : width - 32;
  const skeletonGraphMarginTop = vendor === 'spotify' ? 15 : 4;
  const paddingTopHeader = vendor === 'spotify' ? 16 : 8;
  const xAxisOffset = vendor === 'spotify' ? 95 : 84;
  const errorGraphMarginTop = vendor === 'spotify' ? 46 : 37;

  const streamsTrend = _.path('value', trend);
  const streamsTrendsMarginTop = streamsTrend === 0 ? -3 : 0;
  const streamsTrendsMarginLeft = -4;

  const avgStreamsPerListener = _.path('currentAvg', streamsPerListener);
  const trendStreamsPerListener = _.path('trend.value', streamsPerListener);
  const streamsPerListenerTrendsMarginTop =
    trendStreamsPerListener === 0 ? -4 : 0;
  const trendValueStreamsPerListener = _.path(
    'trend',
    streamsPerListener
  ) as TPositionTrend;

  return (
    <SBox ml={16} position="relative" height={containerHeight} width={width}>
      <SBox height={height + 12} borderRadius={8}>
        <ShadowBox
          height={height}
          bg={theme.colors.eastBay}
          borderRadius={8}
          androidShadowOffset={2}
        >
          <SGradientCard
            colors={theme.gradients.marketCard}
            opacity={0.4}
            height={height}
            borderRadius={8}
          />

          {/* HEADER SECTION */}
          <SBox height={61} pt={paddingTopHeader} px={16}>
            <Media height={32}>
              <SRow pt={2}>
                {showTitleIcon && id ? (
                  <Icon
                    mt={2}
                    ml={-4}
                    mr={5}
                    size={22}
                    color={theme.colors.lavenderGray}
                    name={id as TIconName}
                  />
                ) : null}
                <SGraphTitle>
                  {vendor === 'spotify' ? title : sourceName}
                </SGraphTitle>
              </SRow>
              {id === 'followers' ? (
                <Media.Figure>
                  <SRow
                    bg={theme.colors.pickledBluewood}
                    px={12}
                    height="100%"
                    borderRadius={4}
                  >
                    <SH6 color={theme.colors.periwinkleGray} pr={8} pt={9}>
                      Last Total
                    </SH6>
                    <SH3 medium letterSpacing={1} pt={5}>
                      {lastValue}
                    </SH3>
                  </SRow>
                </Media.Figure>
              ) : null}
            </Media>
          </SBox>

          {/* GRAPH SECTION */}
          <SBox flex={1}>
            {graphVisibility.skeleton ? (
              <SkeletonsSmall
                ml={16}
                mt={skeletonGraphMarginTop}
                width={skeletonGraphWidth}
                height={80}
              />
            ) : null}
            {graphVisibility.error ? (
              <SBox px={16} alignItems="center" mt={errorGraphMarginTop}>
                <SText>Data failed to load.</SText>
              </SBox>
            ) : null}
            {!hideGraph ? (
              <>
                <YAxisLabels
                  ticks={yTicks}
                  scale={yScale}
                  offsetLeft={padding}
                  offsetTop={15}
                  axisExclusion
                />
                <XAxisLabels
                  ticks={ticks!}
                  scale={xScale}
                  yOffset={xAxisOffset}
                  ticksVariant="edge"
                />
                <Svg height={135} width={innerWidth}>
                  <YAxis
                    ticks={yTicks}
                    scale={yScale}
                    xOffsetRight={innerWidth}
                  />
                  <XAxis
                    ticks={ticks!}
                    scale={xScale}
                    yOffset={xAxisOffset}
                    ticksVariant="edge"
                  />
                  <G transform="translate(0, 0)">
                    {dotted ? (
                      <Line
                        graphMax={graphMax}
                        variant={variant}
                        data={dotted}
                        xScale={xScale}
                        yScale={yScale}
                      />
                    ) : null}
                  </G>
                </Svg>
              </>
            ) : null}
          </SBox>

          {/* FOOTER SECTION */}
          <SBox
            bg={theme.colors.pickledBluewood}
            height={110}
            borderBottomLeftRadius={8}
            borderBottomRightRadius={8}
          >
            {/* SPOTIFY STREAMS FOOTER */}
            {id === 'streams' && vendor === 'spotify' ? (
              <SRow px={16} pt={24} justifyContent="space-between">
                <SBox>
                  <SLabel pb={6}>Daily Avg</SLabel>
                  {infoVisibility.skeleton ? <SkeletonsSmall mt={-1} /> : null}
                  {infoVisibility.error ? renderStreamsGraphErrorText() : null}
                  {infoVisibility.data
                    ? renderStreamsGraphFooterData(currentAvg, trend, {
                        ml: streamsTrendsMarginLeft,
                        mt: streamsTrendsMarginTop,
                      })
                    : null}
                </SBox>
                <SBox alignItems="flex-end">
                  <SLabel pb={6}>Streams/Listener</SLabel>
                  {streamsPerListenersVisibility.skeleton ? (
                    <SkeletonsSmall mt={-1} />
                  ) : null}
                  {streamsPerListenersVisibility.error
                    ? renderStreamsGraphErrorText()
                    : null}
                  {streamsPerListenersVisibility.data
                    ? renderStreamsGraphFooterData(
                        avgStreamsPerListener!,
                        trendValueStreamsPerListener,
                        {
                          mt: streamsPerListenerTrendsMarginTop,
                        }
                      )
                    : null}
                </SBox>
              </SRow>
            ) : null}

            {/* APPLE STREAMS FOOTER */}
            {id === 'streams' && (vendor === 'apple' || vendor === 'amazon') ? (
              <SBox alignItems="center" pt={28}>
                <SLabel pb={2}>Daily Avg</SLabel>
                {infoVisibility.skeleton ? <SkeletonsSmall mt={8} /> : null}
                {infoVisibility.error ? renderGraphErrorText() : null}
                {infoVisibility.data
                  ? renderGraphFooterData(currentAvg, trend)
                  : null}
              </SBox>
            ) : null}

            {/* SPOTIFY LISTENERS FOOTER */}
            {id === 'listeners' && vendor === 'spotify' ? (
              <SBox alignItems="center" pt={28}>
                <SLabel pb={2}>Daily Avg</SLabel>
                {infoVisibility.skeleton ? <SkeletonsSmall mt={8} /> : null}
                {infoVisibility.error ? renderGraphErrorText() : null}
                {infoVisibility.data
                  ? renderGraphFooterData(currentAvg, trend)
                  : null}
              </SBox>
            ) : null}

            {/* SPOTIFY FOLLOWERS FOOTER */}
            {id === 'followers' ? (
              <SBox alignItems="center" pt={28}>
                <SLabel pb={2}>Daily Avg Change</SLabel>
                {infoVisibility.skeleton ? <SkeletonsSmall mt={8} /> : null}
                {infoVisibility.error ? renderGraphErrorText() : null}
                {infoVisibility.data
                  ? renderGraphFooterData(currentAvg, trend)
                  : null}
              </SBox>
            ) : null}
          </SBox>
        </ShadowBox>
      </SBox>
      <SBox position="absolute" bottom={0} left={btnLeftPosition} zIndex={1}>
        {graphVisibility.skeleton ? (
          <SkeletonsSmall width={140} height={44} borderRadius={22} />
        ) : null}
        {!hideGraph && onFullScreen ? (
          <Button
            testID="line-graph-details-button"
            onPress={() => {
              onFullScreen();
            }}
            width={btnWidth}
          >
            Details
          </Button>
        ) : null}
      </SBox>
    </SBox>
  );
};

LineGraphNew.defaultProps = {
  title: 'STREAMS',
  showTitleIcon: false,
  variant: 'variant2',
};
