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";
import { useTootEnv } from "../RegularToot";

type TootPollProps = {
  value: mastodon.v1.Poll;
  status: mastodon.v1.Status;
};

const TootPoll: Component<TootPollProps> = (props) => {
  let list: HTMLUListElement;
  const { vote } = useTootEnv();

  const now = useTimeSource();
  const dateFnLocale = useDateFnLocale();
  const [mustShowResult, setMustShowResult] = createSignal<boolean>();
  const [showVoteDialog, setShowVoteDialog] = createSignal(false);

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

  const poll = () => props.value;

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

    return poll().expired || poll().voted;
  };

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

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

    if (poll().expired || poll().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>{poll().votesCount} votes in total</span>
        <Show when={poll().expired}>
          <span>Poll is ended</span>
        </Show>
      </div>
      <List ref={list!} disablePadding class="option-list">
        <Index each={poll().options}>
          {(option, index) => {
            return (
              <>
                <Show when={index === 0}>
                  <Divider />
                </Show>
                <ListItemButton
                  onClick={[openVote, index]}
                  class="poll-item"
                  aria-disabled={isShowResult()}
                >
                  <ListItemText>
                    <span
                      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={poll().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={poll().expiresAt}>
          <span>
            <span style={{ "margin-inline-end": "0.5ch" }}>
              {isBefore(now(), poll().expiresAt!) ? "Expire in" : "Expired"}
            </span>

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

      <TootPollDialog
        open={showVoteDialog()}
        options={poll().options}
        onVote={[vote, props.status]}
        onClose={() => setShowVoteDialog(false)}
        initialVotes={[initialVote()]}
      />
    </section>
  );
};

export default TootPoll;
