import React, { memo } from 'react';

import MuiFormControlLabel from '@mui/material/FormControlLabel';
import type { FormControlLabelProps as MuiFormControlLabelProps } from '@mui/material/FormControlLabel';
import MuiFormGroup from '@mui/material/FormGroup';
import type { FormGroupProps as MuiFormGroupProps } from '@mui/material/FormGroup';
import MuiSwitch from '@mui/material/Switch';
import type { SwitchProps as MuiSwitchProps } from '@mui/material/Switch';
import { styled } from '@mui/material/styles';

import type { Theme } from '../../@styles/theme-provider';

const StyledFormControlLabel = styled(MuiFormControlLabel)(
  ({ theme }: MuiFormControlLabelProps & { theme: Theme }) => ({
    margin: 0,
    justifyContent: 'space-between',
    '& > .MuiFormControlLabel-label.Mui-disabled': {
      color: theme.palette.primary[500]
    },
    '&.MuiFormControlLabel-labelPlacementStart .MuiFormControlLabel-label': {
      marginRight: theme.spacing(1)
    },
    '&.MuiFormControlLabel-labelPlacementEnd .MuiFormControlLabel-label': {
      marginLeft: theme.spacing(1)
    }
  })
);

interface StyledSwitchProps extends MuiSwitchProps {
  hovered?: SwitchProps['hovered'];
}

const StyledSwitch = styled(MuiSwitch, {
  shouldForwardProp: prop => prop !== 'hovered'
})(({ disabled, hovered, theme }: StyledSwitchProps & { theme: Theme }) => ({
  ...(disabled && {
    '&:hover': {
      boxShadow: 'none'
    }
  }),
  ...(hovered &&
    !disabled && {
      boxShadow: theme.shadows[10]
    })
}));

export interface SwitchProps extends MuiSwitchProps {
  /**
   * Whether to display toggle in hovered state.
   * @default false
   */
  hovered?: boolean;
  /**
   * A text or an element to be used in an enclosing label element.
   */
  label?: MuiFormControlLabelProps['label'];
  /**
   * Props that will be passed to the MUI FormControlLabel component.
   */
  labelProps?: Omit<MuiFormControlLabelProps, 'control' | 'label'>;
  /**
   * Display label and switch in a compact row.
   * @default false
   */
  row?: MuiFormGroupProps['row'];
}

const Switch = (props: SwitchProps) => {
  const { label, labelProps, row = false, ...switchProps } = props;

  if (label) {
    return (
      <MuiFormGroup row={row}>
        <StyledFormControlLabel
          value="start"
          control={<StyledSwitch {...switchProps} />}
          label={label}
          labelPlacement="start"
          {...labelProps}
        />
      </MuiFormGroup>
    );
  }

  return <StyledSwitch {...switchProps} />;
};

const m = memo(Switch);
export { m as Switch };
