/* eslint-disable react/display-name */
import React from "react";
import styled, { ThemeProvider } from "styled-components";
import { useTheme } from "@material-ui/core/styles";
import { Clickable, Selectable, Size } from "../Props";
import Card from "@material-ui/core/Card";
import { useDebounce } from "use-debounce";
import { Resizable } from "re-resizable";
import Debug from "debug";
const debug = Debug("userbugreport:Note");

const Resizer = styled(Resizable).attrs(() => ({
  minWidth: 128,
  maxWidth: 480,
  minHeight: 64,
  maxHeight: 480,
}))`
  display: flex;
`;

/**
 * Wrapping card, this gives some depth.
 */
const WrapCard = styled(Card).attrs(() => ({ raised: false }))`
  display: flex;
  flex: 1;
  padding: ${(props) => props.theme.spacing(1)}px;
`;

/**
 * A note is size and text.
 */
export type NoteState = {
  size: Size;
  text: string;
};

/**
 * Configure our Note.
 */
export interface NoteProps extends NoteState, Clickable, Selectable {
  /**
   * Event when the text is changed.
   * This is debounced to avoid lots of noise.
   */
  onChanged?: (note: NoteState) => void;
  style?: React.CSSProperties;
  readonly?: boolean;
}

/**
 * It's a pin graphic, with drag and drop affordance.
 */
export const Note: React.FC<NoteProps> = (props: NoteProps) => {
  debug("render", props);
  // resize enablement
  const enable = props.readonly
    ? false
    : {
        top: false,
        right: true,
        bottom: true,
        left: false,
        topRight: false,
        bottomRight: true,
        bottomLeft: false,
        topLeft: false,
      };
  const theme = useTheme();
  const textAreaRef = React.useRef<HTMLTextAreaElement>();
  // note size is saved here
  const [size, setSize] = React.useState(
    props?.size || { width: 128, height: 64 }
  );
  // real state of the note, initially set to the prop
  const [text, setText] = React.useState(props?.text || "");
  const [textValue] = useDebounce(text, 1000);

  // send along the note state, no need to debounce the sizing
  // as the control appears to send the event on 'sizing done' - which is nice
  React.useEffect(() => {
    props.onChanged && props.onChanged({ text: textValue, size });
  }, [textValue, size]);

  // autofocus
  React.useEffect(() => {
    debug(textAreaRef);
    if (props.selected && textAreaRef.current) {
      textAreaRef.current.focus();
      // move to end
      textAreaRef.current.selectionStart = textAreaRef.current.selectionEnd =
        text?.length || 0;
    }
  }, []);

  return (
    <ThemeProvider theme={theme}>
      <Resizer
        enable={enable}
        defaultSize={size}
        onResizeStop={(_, __, elem) =>
          setSize({
            width: elem.clientWidth,
            height: elem.clientHeight,
          })
        }
      >
        <WrapCard style={props.style}>
          <textarea
            ref={textAreaRef}
            style={{
              flex: 1,
              fontFamily: theme.typography.fontFamily,
              border: 0,
              outline: "none",
              resize: "none",
              backgroundColor: "transparent",
            }}
            readOnly={props.readonly}
            value={text}
            onChange={(e) => setText(e.target.value)}
            onClick={(e) => {
              e.stopPropagation();
              props.onClick && props.onClick(e);
            }}
          />
        </WrapCard>
      </Resizer>
    </ThemeProvider>
  );
};
