import React from 'react';
import styles from './silke-code-snippet.scss';
import { SilkeButton, SilkeButtonSet } from '../silke-button';
import { copyToClipboard } from '../../helpers/copy-to-clipboard';
import { Highlight, Language, PrismTheme, themes } from 'prism-react-renderer';
import { SilkeBox } from '../silke-box';

interface Props {
  buttons?: React.ReactNode;
  code?: string;
  language?: Language;
  lineNumbers?: boolean;
  onCopy?: () => void;
  inlineStyle?: React.CSSProperties;
  noWrap?: boolean;
}

/**
 * Default theme with background removed
 */
export const useTheme: PrismTheme = {
  ...themes.nightOwl,
  plain: {
    ...themes.nightOwl.plain,
    backgroundColor: 'transparent',
    backgroundImage: 'none',
  },
};
export const SilkeCodeSnippet = ({
  buttons,
  code = '',
  language = 'javascript',
  lineNumbers,
  onCopy,
  inlineStyle = {},
  noWrap,
}: Props) => (
  <SilkeBox flex className={styles.main} rounded="small">
    <Highlight theme={useTheme} language={language as Language} code={code}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <pre
          className={className}
          style={{ ...style, ...inlineStyle, whiteSpace: noWrap ? 'pre' : 'pre-wrap' }}
        >
          {tokens.map((line, i) => (
            <div {...(getLineProps({ line, key: i }) as any)} key={i}>
              {lineNumbers && <span className={styles.lineNumber}>{i + 1}</span>}
              {line.map((token, key) => (
                <span {...(getTokenProps({ token, key }) as any)} key={key} />
              ))}
            </div>
          ))}
        </pre>
      )}
    </Highlight>

    <Buttons buttons={buttons} code={code} onCopy={onCopy} />
  </SilkeBox>
);

const Buttons = ({
  buttons,
  code,
  onCopy,
}: {
  buttons?: React.ReactNode;
  code: string;
  onCopy?: () => void;
}) => (
  <SilkeButtonSet size="s" className={styles.buttons} kind="ghost">
    {buttons}
    {onCopy && <CopyButton code={code} onCopy={onCopy} />}
  </SilkeButtonSet>
);

const CopyButton = ({ code, onCopy }: { code: string; onCopy?: () => void }) =>
  code ? (
    <SilkeButton
      icon="copy"
      onClick={() => {
        copyToClipboard(code);
        if (onCopy) onCopy();
      }}
    />
  ) : null;
