import {
  IconButton,
  Divider,
  Box,
  Typography,
  CircularProgress,
  Paper,
} from '@mui/material'
import {
  AddOutlined,
  RemoveOutlined,
  CropFreeOutlined,
} from '@mui/icons-material'
import { styles } from './styles'
import type { ZoomControlProps } from './types'
import { useCallback, type JSX } from 'react'

/**
 * Provides intuitive zoom controls for maps and zoomable interfaces with flexible layouts, loading states, and optional reset functionality.
 *
 * @remarks
 * This is an uncontrolled component. Typically used with the `ZoomControls` HOC from `@carto/ps-react-maps` for automatic state management.
 *
 * @example
 * ```tsx
 * <ZoomControlsUI
 *   zoom={zoom}
 *   onChange={setZoom}
 *   minZoom={2}
 *   maxZoom={20}
 * />
 * ```
 */
export function ZoomControlsUI({
  zoom,
  disabled,
  direction = 'vertical',
  reverse = false,
  isLoading,
  maxZoom = 24,
  minZoom = 0,
  PaperProps,
  ResetViewProps = {
    Icon: CropFreeOutlined,
  },
  showZoom = true,
  onChange,
  onReset,
}: ZoomControlProps): JSX.Element {
  const increaseZoom = useCallback(() => {
    const newZoom = Math.min(maxZoom, zoom + 1)
    onChange(newZoom)
  }, [maxZoom, onChange, zoom])

  const decreaseZoom = useCallback(() => {
    const newZoom = Math.max(minZoom, zoom - 1)
    onChange(newZoom)
  }, [minZoom, onChange, zoom])

  const displayZoom = Math.floor(zoom)

  const dividerOrientation =
    direction === 'vertical' ? 'horizontal' : 'vertical'

  let flexDirection = direction === 'vertical' ? 'column' : 'row'

  if (reverse) {
    flexDirection += '-reverse'
  }

  return (
    <Paper
      sx={{
        ...styles.paper,
        flexDirection,
      }}
      {...PaperProps}
    >
      {onReset && (
        <>
          <IconButton
            onClick={onReset}
            aria-label='Reset action'
            disabled={disabled}
          >
            <ResetViewProps.Icon />
          </IconButton>
          <Divider orientation={dividerOrientation} flexItem />
        </>
      )}
      <IconButton
        onClick={increaseZoom}
        aria-label='Increase zoom'
        disabled={disabled}
      >
        <AddOutlined />
      </IconButton>
      <Divider orientation={dividerOrientation} flexItem />
      {showZoom && (
        <>
          <Box sx={styles.zoom}>
            <Typography
              display='block'
              align='center'
              color='textSecondary'
              variant='overline'
            >
              {displayZoom}
            </Typography>
            {isLoading && (
              <CircularProgress
                sx={styles.circularProgress}
                variant='indeterminate'
                size={24}
              />
            )}
          </Box>
          <Divider orientation={dividerOrientation} flexItem />
        </>
      )}
      <IconButton
        onClick={decreaseZoom}
        aria-label='Decrease zoom'
        disabled={disabled}
      >
        <RemoveOutlined />
      </IconButton>
    </Paper>
  )
}
