import { FunctionComponent } from "react";
import { Notification, PrivateMessageView } from "threadiverse";

import { cx } from "#/helpers/css";
import { SwipeActions } from "#/services/db/types";
import { useAppSelector } from "#/store";

import DMActionsImpl from "./internal/impl/DMActionsImpl";
import ModActionActionsImpl from "./internal/impl/ModActionActionsImpl";
import { VotableActionsImpl } from "./internal/impl/VotableActionsImpl";
import { SlideableVoteItem } from "./internal/shared";

import styles from "./BaseSliding.module.css";

interface BaseSlidingVoteProps extends React.PropsWithChildren {
  className?: string;
  item: SlideableVoteItem;
  notification?: Notification;
  rootIndex?: number;
  collapsed?: boolean;
  actions: SwipeActions;
  onHide?: () => void;
}

function GenericBaseSlidingWrapper<
  T extends
    BaseSlidingVoteProps | BaseSlidingDMProps | BaseSlidingModActionProps,
>({
  component: Component,
  ...props
}: T & {
  component: FunctionComponent<T>;
}) {
  const disableSwipes = useAppSelector(
    (state) =>
      state.gesture.swipe.disableLeftSwipes &&
      state.gesture.swipe.disableRightSwipes,
  );

  if (!disableSwipes) {
    return <Component {...(props as unknown as T)} />;
  } else {
    // don't initialize all the sliding stuff if it's completely unused
    return (
      <div className={cx(props.className, styles.itemContainer)}>
        {props.children}
      </div>
    );
  }
}

export function BaseSlidingVote(props: BaseSlidingVoteProps) {
  return (
    <GenericBaseSlidingWrapper {...props} component={VotableActionsImpl} />
  );
}

export function BaseSlidingDM(props: BaseSlidingDMProps) {
  return <GenericBaseSlidingWrapper {...props} component={DMActionsImpl} />;
}

export function BaseSlidingModAction(props: BaseSlidingModActionProps) {
  return (
    <GenericBaseSlidingWrapper {...props} component={ModActionActionsImpl} />
  );
}

type BaseSlidingDMProps = {
  item: PrivateMessageView;
  notification?: Notification;
} & Omit<BaseSlidingVoteProps, "item" | "notification">;

type BaseSlidingModActionProps = {
  notification?: Notification;
} & Omit<BaseSlidingVoteProps, "item" | "notification">;
