import { useContext, useEffect, useRef, useState } from "react";
import styled, { keyframes } from "styled-components";
import { secondaryDark, vscBackground } from ".";
import {
  ChevronDownIcon,
  ChevronRightIcon,
  ArrowPathIcon,
  XMarkIcon,
  MagnifyingGlassIcon,
  StopCircleIcon,
} from "@heroicons/react/24/outline";
import { HistoryNode } from "../../../schema/HistoryNode";
import HeaderButtonWithText from "./HeaderButtonWithText";
import { getMetaKeyLabel, isMetaEquivalentKeyPressed } from "../util";
import { GUIClientContext } from "../App";
import StyledMarkdownPreview from "./StyledMarkdownPreview";

interface StepContainerProps {
  historyNode: HistoryNode;
  onReverse: () => void;
  inFuture: boolean;
  onUserInput: (input: string) => void;
  onRetry: () => void;
  onDelete: () => void;
  open: boolean;
  onToggleAll: () => void;
  onToggle: () => void;
  isFirst: boolean;
  isLast: boolean;
  index: number;
}

// #region styled components

const MainDiv = styled.div<{
  stepDepth: number;
  inFuture: boolean;
}>`
  opacity: ${(props) => (props.inFuture ? 0.3 : 1)};
  overflow: hidden;
  margin-left: 0px;
  margin-right: 0px;
`;

const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>`
  background-color: ${(props) => (props.error ? "#522" : vscBackground)};
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  padding-right: 8px;
`;

const LeftHeaderSubDiv = styled.div`
  margin: 8px;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  grid-gap: 2px;
`;

const ContentDiv = styled.div<{ isUserInput: boolean }>`
  padding-left: 4px;
  padding-right: 2px;
  background-color: ${(props) =>
    props.isUserInput ? secondaryDark : vscBackground};
  font-size: 13px;
`;

const gradient = keyframes`
  0% {
    background-position: 0px 0;
  }
  100% {
    background-position: 100em 0;
  }
`;

const GradientBorder = styled.div<{
  borderWidth?: number;
  borderRadius?: string;
  borderColor?: string;
  isFirst: boolean;
  isLast: boolean;
  loading: boolean;
}>`
  border-radius: ${(props) => props.borderRadius || "0"};
  padding-top: ${(props) =>
    `${(props.borderWidth || 1) / (props.isFirst ? 1 : 2)}px`};
  padding-bottom: ${(props) =>
    `${(props.borderWidth || 1) / (props.isLast ? 1 : 2)}px`};
  background: ${(props) =>
    props.borderColor
      ? props.borderColor
      : `repeating-linear-gradient(
    101.79deg,
    #12887a 0%,
    #87245c 16%,
    #e12637 33%,
    #ffb215 55%,
    #e12637 67%,
    #87245c 85%,
    #12887a 99%
  )`};
  animation: ${(props) => (props.loading ? gradient : "")} 6s linear infinite;
  background-size: 200% 200%;
`;

// #endregion

function StepContainer(props: StepContainerProps) {
  const [isHovered, setIsHovered] = useState(false);
  const naturalLanguageInputRef = useRef<HTMLTextAreaElement>(null);
  const userInputRef = useRef<HTMLInputElement>(null);
  const isUserInput = props.historyNode.step.name === "UserInputStep";
  const client = useContext(GUIClientContext);

  useEffect(() => {
    if (userInputRef?.current) {
      userInputRef.current.focus();
    }
  }, [userInputRef]);

  useEffect(() => {
    if (isHovered) {
      naturalLanguageInputRef.current?.focus();
    }
  }, [isHovered]);

  return (
    <MainDiv
      stepDepth={(props.historyNode.depth as any) || 0}
      inFuture={props.inFuture}
      onMouseEnter={() => {
        setIsHovered(true);
      }}
      onMouseLeave={() => {
        setIsHovered(false);
      }}
      hidden={props.historyNode.step.hide as any}
    >
      <div>
        <GradientBorder
          loading={props.historyNode.active as boolean}
          isFirst={props.isFirst}
          isLast={props.isLast}
          borderColor={
            props.historyNode.observation?.error
              ? "#f005"
              : props.historyNode.active
              ? undefined
              : "transparent"
          }
          className="overflow-hidden cursor-pointer"
          onClick={(e) => {
            if (isMetaEquivalentKeyPressed(e)) {
              props.onToggleAll();
            } else {
              props.onToggle();
            }
          }}
        >
          <HeaderDiv
            loading={(props.historyNode.active as boolean) || false}
            error={props.historyNode.observation?.error ? true : false}
          >
            <LeftHeaderSubDiv
              style={
                props.historyNode.observation?.error ? { color: "white" } : {}
              }
            >
              {!isUserInput &&
                (props.open ? (
                  <ChevronDownIcon width="1.4em" height="1.4em" />
                ) : (
                  <ChevronRightIcon width="1.4em" height="1.4em" />
                ))}
              {props.historyNode.observation?.title ||
                (props.historyNode.step.name as any)}
            </LeftHeaderSubDiv>
            {/* <HeaderButton
              onClick={(e) => {
                e.stopPropagation();
                props.onReverse();
              }}
            >
              <Backward size="1.6em" onClick={props.onReverse}></Backward>
            </HeaderButton> */}
            {(isHovered || (props.historyNode.active as boolean)) && (
              <div className="flex gap-2 items-center">
                {(props.historyNode.logs as any)?.length > 0 && (
                  <HeaderButtonWithText
                    text="Logs"
                    onClick={(e) => {
                      e.stopPropagation();
                      client?.showLogsAtIndex(props.index);
                    }}
                  >
                    <MagnifyingGlassIcon width="1.4em" height="1.4em" />
                  </HeaderButtonWithText>
                )}
                <HeaderButtonWithText
                  onClick={(e) => {
                    e.stopPropagation();
                    props.onDelete();
                  }}
                  text={
                    props.historyNode.active
                      ? `Stop (${getMetaKeyLabel()}⌫)`
                      : "Delete"
                  }
                >
                  {props.historyNode.active ? (
                    <StopCircleIcon
                      width="1.4em"
                      height="1.4em"
                      onClick={props.onDelete}
                    />
                  ) : (
                    <XMarkIcon
                      width="1.4em"
                      height="1.4em"
                      onClick={props.onDelete}
                    />
                  )}
                </HeaderButtonWithText>
                {props.historyNode.observation?.error ? (
                  <HeaderButtonWithText
                    text="Retry"
                    onClick={(e) => {
                      e.stopPropagation();
                      props.onRetry();
                    }}
                  >
                    <ArrowPathIcon
                      width="1.4em"
                      height="1.4em"
                      onClick={props.onRetry}
                    />
                  </HeaderButtonWithText>
                ) : (
                  <></>
                )}
              </div>
            )}
          </HeaderDiv>
        </GradientBorder>
        <ContentDiv hidden={!props.open} isUserInput={isUserInput}>
          {props.open && false && (
            <>
              <pre className="overflow-x-scroll">
                Step Details:
                <br />
                {JSON.stringify(props.historyNode.step, null, 2)}
              </pre>
            </>
          )}

          {props.historyNode.observation?.error ? (
            <details>
              <summary>View Traceback</summary>
              <pre className="overflow-x-scroll">
                {props.historyNode.observation.error as string}
              </pre>
            </details>
          ) : (
            <StyledMarkdownPreview
              source={props.historyNode.step.description || ""}
              wrapperElement={{
                "data-color-mode": "dark",
              }}
            />
          )}
        </ContentDiv>
      </div>
    </MainDiv>
  );
}

export default StepContainer;