import { scaleLinear } from 'd3-scale'
import React from 'react'
import { LayoutChangeEvent, StyleProp, View, ViewStyle } from 'react-native'
import Svg, { Defs, G } from 'react-native-svg'

export interface Size {
  width: number
  height: number
}

export interface Padding {
  left: number
  right: number
  top: number
  bottom: number
}

interface DataSet {
  domain: [number, number]
  dataLength: number
}

export function useFigure({
  size,
  plotPadding,
  dataSets,
}: {
  size: Size | null
  plotPadding: Padding
  dataSets: DataSet[]
}) {
  if (!size) {
    return null
  }

  const padding = {
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
  }

  const contentSize = {
    width: size.width - padding.left - padding.right,
    height: size.height - padding.top - padding.bottom,
  }

  const scaleX = dataSets.map(({ dataLength }) =>
    scaleLinear()
      .domain([0, dataLength])
      .range([plotPadding.left, contentSize.width - plotPadding.right])
  )

  const scaleY = dataSets.map(({ domain }) =>
    scaleLinear()
      .domain(domain)
      .range([contentSize.height - plotPadding.top, plotPadding.bottom])
      .nice(4)
  )

  return { contentSize, padding, scaleX, scaleY, Figure }
}

export const Figure: React.FC<{
  onLayout: (e: LayoutChangeEvent) => void
  size: Size
  patterns?: React.ReactElement
  padding: Padding
  style?: StyleProp<ViewStyle>
  pressable?: boolean
}> = ({
  onLayout,
  size,
  patterns,
  padding,
  children,
  style,
  pressable = false,
}) => {
  return (
    <View
      style={[style ?? { flex: 1 }]}
      onLayout={onLayout}
      pointerEvents={
        pressable ? 'auto' : 'none' /* prevent figure from capturing clicks */
      }
    >
      {size.width > 0 && size.height > 0 ? (
        <Svg viewBox={`0 0 ${size.width} ${size.height}`}>
          {patterns != null ? <Defs>{patterns}</Defs> : null}
          <G transform={`translate(${padding.left}, ${padding.top})`}>
            {children}
          </G>
        </Svg>
      ) : null}
    </View>
  )
}
