import {
  Button,
  ButtonGroup,
  Icon,
  NumericInput,
  Tag,
} from "@blueprintjs/core";

const styles = {
  container: {
    display: "flex",
    alignItems: "center",
    paddingRight: 5,
    marginRight: -15,
  },
  inputWrapper: {
    /**
     * As of Feb'22, NumericInput doesn't have `small` prop yet,
     * so we instead use `transform` to hack up a slightly smaller input.
     */
    transform: "scale(0.9)",
    marginLeft: 10,
  },
  input: {
    width: 125,
  },
};

/** Possible states of the debug controls component */
type DebugControlsState = "off" | "running" | "paused" | "error";

/** Input field for changing execution interval */
const IntervalInput = (props: {
  disabled: boolean;
  onChange: (v: number) => void;
}) => {
  return (
    <div style={styles.inputWrapper}>
      <NumericInput
        min={5}
        stepSize={5}
        defaultValue={20}
        minorStepSize={null}
        leftIcon="time"
        clampValueOnBlur
        style={styles.input}
        disabled={props.disabled}
        title="Adjust the execution interval"
        onValueChange={(v) => props.onChange(v)}
        rightElement={<Tag minimal>ms</Tag>}
        allowNumericCharactersOnly
      />
    </div>
  );
};

/** Button for starting code execution */
const RunButton = ({ onClick }: { onClick: () => void }) => (
  <Button
    outlined
    intent="success"
    onClick={onClick}
    rightIcon={<Icon icon="play" intent="success" />}
    title="Run your code"
  >
    Run code
  </Button>
);

/** Button group for debugging controls */
const DebugControls = (props: {
  state: DebugControlsState;
  onPause: () => void;
  onResume: () => void;
  onStep: () => void;
  onStop: () => void;
}) => {
  const paused = props.state === "paused" || props.state === "error";
  const pauseDisabled = props.state === "error";
  const stepDisabled = ["off", "running", "error"].includes(props.state);

  return (
    <ButtonGroup>
      <Button
        outlined
        intent="primary"
        title={paused ? "Resume" : "Pause"}
        disabled={pauseDisabled}
        onClick={paused ? props.onResume : props.onPause}
        icon={<Icon icon={paused ? "play" : "pause"} intent="primary" />}
      />
      <Button
        outlined
        intent="warning"
        title="Step"
        onClick={props.onStep}
        disabled={stepDisabled}
        icon={<Icon icon="step-forward" intent="warning" />}
      />
      <Button
        outlined
        intent="danger"
        title="Stop"
        onClick={props.onStop}
        icon={<Icon icon="stop" intent="danger" />}
      />
    </ButtonGroup>
  );
};

type Props = {
  state: DebugControlsState;
  onRun: () => void;
  onPause: () => void;
  onResume: () => void;
  onStep: () => void;
  onStop: () => void;
  onChangeInterval: (value: number) => void;
};

export const ExecutionControls = (props: Props) => {
  return (
    <div style={styles.container}>
      {props.state === "off" ? (
        <RunButton onClick={props.onRun} />
      ) : (
        <DebugControls
          state={props.state}
          onPause={props.onPause}
          onResume={props.onResume}
          onStep={props.onStep}
          onStop={props.onStop}
        />
      )}
      <IntervalInput
        disabled={props.state === "running"}
        onChange={props.onChangeInterval}
      />
    </div>
  );
};