import emojiRegex from "emoji-regex";
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useHistory, useRouteMatch } from "react-router-dom";
import styled from "styled-components";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import { useDocumentContext } from "~/components/DocumentContext";
import DocumentViews from "~/components/DocumentViews";
import Flex from "~/components/Flex";
import ListItem from "~/components/List/Item";
import PaginatedList from "~/components/PaginatedList";
import Text from "~/components/Text";
import Time from "~/components/Time";
import useKeyDown from "~/hooks/useKeyDown";
import useStores from "~/hooks/useStores";
import useTextSelection from "~/hooks/useTextSelection";
import { documentUrl } from "~/utils/routeHelpers";
import Sidebar from "./SidebarLayout";

function Insights() {
  const { views, documents } = useStores();
  const { t } = useTranslation();
  const match = useRouteMatch<{ documentSlug: string }>();
  const history = useHistory();
  const selectedText = useTextSelection();
  const document = documents.getByUrl(match.params.documentSlug);
  const { editor } = useDocumentContext();
  const text = editor?.getPlainText();
  const stats = useTextStats(text ?? "", selectedText);
  const documentViews = document ? views.inDocument(document.id) : [];

  const onCloseInsights = () => {
    if (document) {
      history.push(documentUrl(document));
    }
  };

  useKeyDown("Escape", onCloseInsights);

  return (
    <Sidebar title={t("Insights")} onClose={onCloseInsights}>
      {document ? (
        <>
          <Content column>
            <Heading>{t("Stats")}</Heading>
            <Text type="secondary" size="small">
              <List>
                {stats.total.words > 0 && (
                  <li>
                    {t(`{{ count }} minute read`, {
                      count: stats.total.readingTime,
                    })}
                  </li>
                )}
                <li>{t(`{{ count }} words`, { count: stats.total.words })}</li>
                <li>
                  {t(`{{ count }} characters`, {
                    count: stats.total.characters,
                  })}
                </li>
                <li>
                  {t(`{{ number }} emoji`, { number: stats.total.emoji })}
                </li>
                {stats.selected.characters === 0 ? (
                  <li>{t("No text selected")}</li>
                ) : (
                  <>
                    <li>
                      {t(`{{ count }} words selected`, {
                        count: stats.selected.words,
                      })}
                    </li>
                    <li>
                      {t(`{{ count }} characters selected`, {
                        count: stats.selected.characters,
                      })}
                    </li>
                  </>
                )}
              </List>
            </Text>
          </Content>
          <Content column>
            <Heading>{t("Collaborators")}</Heading>
            <Text type="secondary" size="small">
              {t(`Created`)} <Time dateTime={document.createdAt} addSuffix />.
              <br />
              {t(`Last updated`)}{" "}
              <Time dateTime={document.updatedAt} addSuffix />.
            </Text>
            <ListSpacing>
              <PaginatedList
                aria-label={t("Collaborators")}
                items={document.collaborators}
                renderItem={(model: User) => (
                  <ListItem
                    key={model.id}
                    title={model.name}
                    image={<Avatar model={model} size={32} />}
                    subtitle={
                      model.id === document.createdBy.id
                        ? t("Creator")
                        : model.id === document.updatedBy.id
                        ? t("Last edited")
                        : t("Previously edited")
                    }
                    border={false}
                    small
                  />
                )}
              />
            </ListSpacing>
          </Content>
          <Content column>
            <Heading>{t("Views")}</Heading>
            <Text type="secondary" size="small">
              {documentViews.length <= 1
                ? t("No one else has viewed yet")
                : t(`Viewed {{ count }} times by {{ teamMembers }} people`, {
                    count: documentViews.reduce(
                      (memo, view) => memo + view.count,
                      0
                    ),
                    teamMembers: documentViews.length,
                  })}
              .
            </Text>
            {documentViews.length > 1 && (
              <ListSpacing>
                <DocumentViews document={document} isOpen />
              </ListSpacing>
            )}
          </Content>
        </>
      ) : null}
    </Sidebar>
  );
}

function useTextStats(text: string, selectedText: string) {
  const numTotalWords = countWords(text);
  const regex = emojiRegex();
  const matches = Array.from(text.matchAll(regex));

  return {
    total: {
      words: numTotalWords,
      characters: text.length,
      emoji: matches.length ?? 0,
      readingTime: Math.max(1, Math.floor(numTotalWords / 200)),
    },
    selected: {
      words: countWords(selectedText),
      characters: selectedText.length,
    },
  };
}

function countWords(text: string): number {
  const t = text.trim();

  // Hyphenated words are counted as two words
  return t ? t.replace(/-/g, " ").split(/\s+/g).length : 0;
}

const ListSpacing = styled("div")`
  margin-top: -0.5em;
  margin-bottom: 0.5em;
`;

const List = styled("ul")`
  margin: 0;
  padding: 0;
  list-style: none;

  li:before {
    content: "·";
    display: inline-block;
    font-weight: 600;
    color: ${(props) => props.theme.textTertiary};
    width: 10px;
  }
`;

const Content = styled(Flex)`
  padding: 0 16px;
  user-select: none;
`;

const Heading = styled("h3")`
  font-size: 15px;
`;

export default observer(Insights);
