import {
  batch,
  createRenderEffect,
  createSelector,
  createSignal,
  Index,
  Show,
  untrack,
  type Component,
} from "solid-js";
import "./TootPoll.css";
import type { mastodon } from "masto";
import { resolveCustomEmoji } from "../../masto/toot";
import {
  Button,
  Checkbox,
  Divider,
  List,
  ListItemButton,
  ListItemText,
  Radio,
} from "@suid/material";
import {
  formatDistance,
  isBefore,
} from "date-fns";
import { useTimeSource } from "~platform/timesrc";
import { useDateFnLocale } from "~platform/i18n";
import TootPollDialog from "./TootPollDialog";
import { ANIM_CURVE_STD } from "~material/theme";

type TootPollProps = {
  options: Readonly<mastodon.v1.Poll["options"]>;
  multiple?: boolean;
  votesCount: number;
  expired?: boolean;
  expiredAt?: Date;
  voted?: boolean;
  ownVotes?: readonly number[];

  onVote(votes: readonly number[]): void | Promise<void>;
};

const TootPoll: Component<TootPollProps> = (props) => {
  let list: HTMLUListElement;
  const now = useTimeSource();
  const dateFnLocale = useDateFnLocale();
  const [mustShowResult, setMustShowResult] = createSignal<boolean>();
  const [showVoteDialog, setShowVoteDialog] = createSignal(false);

  const [initialVote, setInitialVote] = createSignal(0);

  const isShowResult = () => {
    const n = mustShowResult();
    if (typeof n !== "undefined") {
      return n;
    }

    return props.expired || props.voted;
  };

  const isOwnVote = createSelector(
    () => props.ownVotes,
    (idx: number, votes) => votes?.includes(idx) || false,
  );

  const openVote = (i: number, event: Event) => {
    event.stopPropagation();

    if (props.expired || props.voted) {
      return;
    }

    batch(() => {
      setInitialVote(i);
      setShowVoteDialog(true);
    });
  };

  const animateAndSetMustShow = (event: Event) => {
    event.stopPropagation();
    list.animate(
      {
        opacity: [0.5, 0, 0.5],
      },
      {
        duration: 220,
        easing: ANIM_CURVE_STD,
      },
    );
    setMustShowResult((x) => {
      if (typeof x === "undefined") {
        return !untrack(isShowResult);
      } else {
        return undefined;
      }
    });
  };

  return (
    <section class="TootPoll">
      <div class="hints">
        <span>{props.votesCount} votes in total</span>
        <Show when={props.expired}>
          <span>Poll is ended</span>
        </Show>
      </div>
      <List ref={list!} disablePadding class="option-list">
        <Index each={props.options}>
          {(option, index) => {
            return (
              <>
                <Show when={index === 0}>
                  <Divider />
                </Show>
                <ListItemButton
                  onClick={[openVote, index]}
                  class="poll-item"
                  aria-disabled={isShowResult()}
                >
                  <ListItemText>
                    <span
                      ref={(e) =>
                        createRenderEffect(() => {
                          e.innerHTML = resolveCustomEmoji(
                            option().title,
                            option().emojis,
                          );
                        })
                      }
                    ></span>
                  </ListItemText>

                  <Show when={isShowResult()}>
                    <span>
                      <Show when={typeof option().votesCount !== "undefined"}>
                        {option().votesCount} votes
                      </Show>
                    </span>
                  </Show>

                  <Show
                    when={props.multiple}
                    fallback={
                      <Radio
                        checked={isOwnVote(index)}
                        disabled={isShowResult()}
                      />
                    }
                  >
                    <Checkbox
                      checked={isOwnVote(index)}
                      disabled={isShowResult()}
                    />
                  </Show>
                </ListItemButton>
                <Divider />
              </>
            );
          }}
        </Index>
      </List>
      <div class="trailers">
        <Button onClick={animateAndSetMustShow}>
          {isShowResult() ? "Hide result" : "Reveal result"}
        </Button>
        <Show when={props.expiredAt}>
          <span>
            <span style={{ "margin-inline-end": "0.5ch" }}>
              {isBefore(now(), props.expiredAt!) ? "Expire in" : "Expired"}
            </span>

            <time dateTime={props.expiredAt!.toISOString()}>
              {formatDistance(now(), props.expiredAt!, {
                locale: dateFnLocale(),
              })}
            </time>
          </span>
        </Show>
      </div>

      <TootPollDialog
        open={showVoteDialog()}
        options={props.options}
        onVote={(votes) => console.debug(votes)}
        onClose={() => setShowVoteDialog(false)}
        initialVotes={[initialVote()]}
      />
    </section>
  );
};

export default TootPoll;
