import React from 'react';
import {
  LiveProvider as _LiveProvider,
  LivePreview as _LivePreview,
  LiveEditor as _LiveEditor,
  LiveError as _LiveError
} from 'react-live';
import { withMDXComponents } from '@mdx-js/tag/dist/mdx-provider';
import base64url from 'base64-url';
import CopyToClipboard from 'react-copy-to-clipboard';

import { Box, Button, Toast, palette, styled } from 'fannypack';

const LiveEditor = styled(_LiveEditor)`
  font-family: Menlo, monospace;
  padding: 1.5em;
  margin: 0;
  background-color: ${palette('white700')};
  overflow-x: auto;
  outline: none;
`;
const LiveError = styled(_LiveError)`
  font-family: Menlo, monospace;
  padding: 1em;
  margin: 0;
  background-color: ${palette('danger')};
  color: ${palette('dangerInverted')};
  overflow-x: auto;
`;
const LivePreview = styled(_LivePreview)`
  padding: 1.5em;
`;
const LiveProvider = styled(_LiveProvider)`
  border: 1px solid ${palette('white700')};
  border-radius: 2;
  margin-top: 1em;
  margin-bottom: 1em;
`;

export const LiveCode = withMDXComponents(({ components, scope, ...props }) => {
  const [code, setCode] = React.useState(props.code);

  const playroomUrl = React.useMemo(() => {
    return `/playroom/#?code=${code ? base64url.encode(code) : ''}`;
  }, [code]);

  function handleClickPlayroom() {
    window.open(playroomUrl, '_blank');
  }

  return (
    <Box marginBottom="major-4">
      <LiveProvider
        scope={{
          ...components,
          ...scope
        }}
        {...props}
        code={code}
      >
        <LivePreview />
        <Box relative>
          <Box absolute top="0.25rem" right="0.25rem">
            <Toast.Container>
              {toast => (
                <CopyToClipboard text={code} onCopy={() => toast.success({ title: 'Copied snippet to clipboard' })}>
                  <Button kind="ghost" palette="primary" size="small">
                    Copy
                  </Button>
                </CopyToClipboard>
              )}
            </Toast.Container>
            <Button kind="ghost" palette="primary" size="small" onClick={handleClickPlayroom}>
              Playroom
            </Button>
          </Box>
          <LiveEditor onChange={setCode} />
        </Box>
        <LiveError />
      </LiveProvider>
    </Box>
  );
});

LiveCode.defaultProps = {
  mountStylesheet: false,
  transformCode: src => `<React.Fragment>${src}</React.Fragment>`
};

const REG = /language\-\.jsx/; // eslint-disable-line

export const MDXLive = ({ pre: Pre, fallback: Fallback, match = REG, children, metaString, ...props }) => {
  const isLive = match.test(props.className);
  const Comp = Pre || Fallback;
  if (!isLive) {
    const lang = (props.className || '').split('-')[1];
    return (
      <Comp {...props} lang={lang}>
        {children.replace(/\n$/, '')}
      </Comp>
    );
  }

  const code = React.Children.toArray(children).join('\n');

  return <LiveCode {...props} code={code} />;
};

export default MDXLive;
