import React from 'react';
import styled from 'styled-components';

import type { FileTabs } from '@redocly/theme/components/CodeBlock/CodeBlock';

import { CodeBlockTabs } from '@redocly/theme/components/CodeBlock/CodeBlockTabs';
import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
import { useThemeHooks, useThemeConfig } from '@redocly/theme/core/hooks';
import { DeselectIcon } from '@redocly/theme/icons/DeselectIcon/DeselectIcon';
import { MaximizeIcon } from '@redocly/theme/icons/MaximizeIcon/MaximizeIcon';
import { MinimizeIcon } from '@redocly/theme/icons/MinimizeIcon/MinimizeIcon';
import { SelectIcon } from '@redocly/theme/icons/SelectIcon/SelectIcon';
import { WarningSquareIcon } from '@redocly/theme/icons/WarningSquareIcon/WarningSquareIcon';
import { Button } from '@redocly/theme/components/Button/Button';

export type CodeBlockControlsProps = {
  children?: React.ReactNode;
  className?: string;
  title?: React.ReactNode | string;
  controls?: ControlItems | false;
  tabs?: FileTabs;
};

type ControlItems = {
  copy?: CopyControlProps;
  expand?: ControlProps;
  collapse?: ControlProps;
  report?: ControlProps;
  select?: ControlProps;
  deselect?: ControlProps;
};

type ControlProps = {
  hidden?: boolean;
  label?: string;
  tooltipText?: string;
  onClick?: () => void;
  props?: Record<string, any>;
};

type CopyControlProps = ControlProps & {
  data?: string;
  dataSource?: string;
  dataHash?: string;
  toasterPlacement?: 'left' | 'right' | 'top' | 'bottom';
  toasterText?: string;
  toasterDuration?: number;
  handleOutside?: boolean;
};

export type ControlItemType = 'text' | 'icon';

export function CodeBlockControls({
  children,
  className,
  title,
  controls,
  tabs,
}: CodeBlockControlsProps): JSX.Element | null {
  const { codeSnippet } = useThemeConfig();
  const { useTelemetry } = useThemeHooks();
  const telemetry = useTelemetry();
  const controlsType = (codeSnippet?.elementFormat as ControlItemType) || 'icon';
  const { copy, expand, collapse, select, deselect, report } = controls || {
    copy: null,
    expand: null,
    collapse: null,
    select: null,
    deselect: null,
    report: null,
  };

  const defaultControls = controls ? (
    <>
      {title && <Title>{title}</Title>}
      {tabs && <CodeBlockTabs tabs={tabs} />}
      <ControlsWrapper>
        {report && !report?.props?.hide ? (
          <ControlButton
            variant="text"
            size="small"
            data-testid="report-button"
            icon={controlsType === 'icon' ? <WarningSquareIcon size="18px" /> : undefined}
            {...report.props}
          >
            {controlsType != 'icon' && (report.props?.buttonText || 'Report')}
          </ControlButton>
        ) : null}

        {expand && !codeSnippet?.expand?.hide ? (
          <ControlButton
            variant="text"
            size="small"
            data-testid="expand-all"
            icon={controlsType === 'icon' ? <MaximizeIcon /> : undefined}
            onClick={expand?.onClick}
          >
            {controlsType !== 'icon' && (expand?.label || 'Expand all')}
          </ControlButton>
        ) : null}

        {collapse && !codeSnippet?.collapse?.hide ? (
          <ControlButton
            variant="text"
            size="small"
            data-testid="collapse-all"
            icon={controlsType === 'icon' ? <MinimizeIcon /> : undefined}
            onClick={collapse?.onClick}
          >
            {controlsType !== 'icon' && (expand?.label || 'Collapse all')}
          </ControlButton>
        ) : null}

        {select ? (
          <ControlButton
            variant="text"
            size="small"
            data-testid="select-all"
            icon={controlsType === 'icon' ? <SelectIcon /> : undefined}
            onClick={select?.onClick}
          >
            {controlsType !== 'icon' && select?.label ? select.label : 'Select all'}
          </ControlButton>
        ) : null}

        {deselect ? (
          <ControlButton
            variant="text"
            size="small"
            data-testid="clear-all"
            icon={controlsType === 'icon' ? <DeselectIcon /> : undefined}
            onClick={deselect?.onClick}
          >
            {controlsType !== 'icon' && deselect?.label ? deselect.label : 'Clear all'}
          </ControlButton>
        ) : null}

        {copy && !codeSnippet?.copy?.hide ? (
          <CopyButton
            data={copy.data}
            data-source={copy.dataSource}
            data-hash={copy.dataHash}
            type={controlsType}
            toasterPlacement={copy.toasterPlacement}
            toasterDuration={copy.toasterDuration}
            buttonText={copy.label}
            onCopyClick={() => {
              copy?.onClick?.();
              telemetry?.send?.('code_snippet_copied', {});
            }}
          />
        ) : null}
      </ControlsWrapper>
    </>
  ) : null;

  return children || controls ? (
    <ContainerWrapper data-component-name="CodeBlock/CodeBlockControls" className={className}>
      {children ? children : defaultControls}
    </ContainerWrapper>
  ) : null;
}

const ContainerWrapper = styled.div`
  display: grid;
  justify-content: end;
  font-size: var(--code-block-controls-font-size);
  font-family: var(--code-block-controls-font-family);
  background-color: var(--code-block-controls-bg-color);
  padding: var(--code-block-controls-padding);
  border-bottom: var(--code-block-controls-border);
  line-height: var(--line-height-lg);
  min-height: var(--control-height-base);
  grid-template-columns: 1fr auto;
`;

const Title = styled.span`
  display: flex;
  align-items: center;
  color: var(--code-block-controls-text-color);
  width: 100%;
  font-weight: var(--code-block-controls-font-weight);
`;

const ControlsWrapper = styled.div`
  display: flex;
  text-align: right;
  align-items: center;
  gap: var(--spacing-xxs);
  justify-content: end;
  margin-left: var(--spacing-sm);
`;

const ControlButton = styled(Button)`
  & + & {
    margin-left: 0;
  }
`;
