// @flow
import { indexOf, min, max, isEmpty } from 'lodash';
import React from 'react';
import styled from 'styled-components';
import type { ThemeProps, TranslatedContent } from '../../../types';

import { Box } from '../../../primitives';
import { Text, Head5 } from '../../typography';
import { getPaletteColor } from '../../../mixins/branding';

type RangeProps = {
  selectedScore: number,
  permittedScores: Array<number>,
  minLabel?: TranslatedContent,
  maxLabel?: TranslatedContent,
  onRangeChange: number => void,
};

const getRangeInputBackgroundColor = ({
  theme,
  greyOut,
}: ThemeProps & { greyOut: boolean }) => {
  const colorCode = greyOut ? 'greyscale-medium' : 'brand-secondary-base';
  return getPaletteColor(colorCode)({ theme });
};

const getWidth = ({ value, options }) => {
  const index = indexOf(options, value);
  // want 0-indexed length
  return `${(index / (options.length - 1)) * 100}`;
};

const StyledRangeInput = styled.input`
  appearance: none;
  margin: 12px 0 0;
  width: 100%;
  height: 6px;

  background: linear-gradient(
    to right,
    ${getRangeInputBackgroundColor} 0%,
    ${getRangeInputBackgroundColor} ${getWidth}%,
    ${getPaletteColor('greyscale-light')} ${getWidth}%,
    ${getPaletteColor('greyscale-light')} 100%
  );

  ::-webkit-slider-runnable-track {
    border-radius: 3px;
    cursor: pointer;
    height: 6px;
    width: 100%;
  }

  ::-webkit-slider-thumb {
    appearance: none;
    background: #fff;

    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    cursor: pointer;
    height: 20px;
    margin-top: -7px;
    width: 20px;
  }

  ::-moz-range-track {
    background: ${getPaletteColor('greyscale-light')};
    border-radius: 3px;
    cursor: pointer;
    height: 6px;
    width: 100%;
  }

  ::-moz-range-thumb {
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    cursor: pointer;
    height: 20px;
    width: 20px;
  }

  ::-moz-range-progress {
    background: ${getRangeInputBackgroundColor};
    border-radius: 3px;
    cursor: pointer;
    height: 6px;
    width: 100%;
  }

  ::-ms-track {
    background: transparent;
    border-color: transparent;
    color: transparent;
    cursor: pointer;
    height: 6px;
    width: 100%;
  }

  ::-ms-fill-lower {
    background: ${getRangeInputBackgroundColor};
    border-radius: 3px;
  }

  ::-ms-fill-upper {
    background: ${getPaletteColor('greyscale-light')};
    border-radius: 3px;
  }

  ::-ms-thumb {
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    cursor: pointer;
    height: 20px;
    width: 20px;
  }

  :focus {
    outline: none;
  }

  ::-webkit-slider-thumb:focus,
  ::-moz-range-thumb:focus,
  ::-ms-range-thumb:focus {
    border: 2px solid ${getPaletteColor('greyscale-darker')};
  }
`;

export const NoMarginText = styled(Text)`
  margin-bottom: 0;
`;

const SliderContainer = styled(Box)`
  position: relative;
  width: 100%;
`;

const SliderLabel = styled(Head5)`
  color: ${getPaletteColor('greyscale-dark')};
`;

const Labels = ({
  minLabel,
  maxLabel,
}: {
  minLabel: TranslatedContent,
  maxLabel: TranslatedContent,
}) => (
  <React.Fragment>
    <SliderLabel align="left">{minLabel}</SliderLabel>
    <SliderLabel align="right">{maxLabel}</SliderLabel>
  </React.Fragment>
);

const LegendContainer = ({ children }: { children: React$Node }) => (
  <Box stacked="row" justify="space-between" align="center" spacing="pt1">
    {children}
  </Box>
);

export const Range = ({
  selectedScore,
  permittedScores,
  onRangeChange,
  // $FlowFixMe - TranslatedContent contains string but some reason flow is saying there's a type conflict between React.Element and String
  minLabel = '',
  // $FlowFixMe - TranslatedContent contains string but some reason flow is saying there's a type conflict between React.Element and String
  maxLabel = '',
}: RangeProps) => {
  const minimumScore = min(permittedScores);
  const maximumScore = max(permittedScores);

  return (
    <SliderContainer spacing="mt1">
      <StyledRangeInput
        type="range"
        min={minimumScore}
        max={maximumScore}
        options={permittedScores}
        value={selectedScore}
        onChange={event => onRangeChange(parseInt(event.target.value, 10))}
      />
      <LegendContainer>
        <Labels
          minLabel={isEmpty(minLabel) ? minimumScore.toString() : minLabel}
          maxLabel={isEmpty(maxLabel) ? maximumScore.toString() : maxLabel}
        />
      </LegendContainer>
    </SliderContainer>
  );
};
