import * as React from "react";
import { Loading } from "./Loading";
import { Card } from "./Card";
import { GridLayout } from "@egjs/react-infinitegrid";
import ReactModal from "react-modal";
import { FullCard, fullcardStyles } from "./FullCard";
import {
  CardProps,
  CardRequestProps,
  CardState,
  CardStateHandler
} from "./types";

const { useState, useCallback, useEffect } = React;

export const Cards = ({ rootUrl }: { rootUrl: string }) => {
  const emptyCards: CardState = {
    cards: [],
    first: rootUrl,
    next: rootUrl,
    maxCards: -1
  };

  const [cards, setCards]: CardStateHandler = useState(emptyCards);
  const [loading, setLoading]: [boolean, Function] = useState(false);
  const [currentCard, setCurrentCard]: [CardProps | null, Function] = useState(
    null
  );

  // Good GRIEF, the things we have to do convince React to actually
  // draw sometimes.
  useEffect(() => {
    if (cards.first !== rootUrl) {
      setCards(emptyCards);
    }
  }, [cards.first, rootUrl, emptyCards]);

  // Debounce that annoying loopback.
  const loadItems = useCallback(() => {
    if (cards.next === null || cards.cards.length === cards.maxCards) {
      return;
    }

    const request = new Request(cards.next);
    fetch(request)
      .then(response => response.json())
      .then((data: CardRequestProps) => {
        setCards({
          ...cards,
          cards: [...cards.cards, ...data.cards],
          next: data._links && data._links.next ? data._links.next : null,
          maxcards: data._totalCount
        });
        setLoading(false);
      });
  }, [cards]);

  const loadMoreCards = (options: any) => {
    if (options.startLoading !== null) {
      options.startLoading();
    }
    loadItems();
  };

  const onLayoutComplete = (options: any) => {
    !options.isLayout && options.endLoading();
  };

  const handleCloseCard = () => {
    setCurrentCard(null);
  };

  const handleOpenCard = (id: string) => {
    const card = cards.cards.find(card => card.id === id);
    if (card) {
      setCurrentCard(card);
    }
  };

  return (
    <div className="container">
      <ReactModal
        isOpen={currentCard !== null}
        style={fullcardStyles}
        contentLabel=""
        onRequestClose={handleCloseCard}
      >
        <FullCard card={currentCard} />
      </ReactModal>
      <GridLayout
        options={{
          isConstantSize: true,
          isEqualSize: true,
          transitionDuration: 0.2
        }}
        layoutOptions={{
          margin: 10
        }}
        onAppend={loadMoreCards}
        onLayoutComplete={onLayoutComplete}
      >
        {cards.cards.map((card: CardProps, count: number) => (
          <Card card={card} key={count} onClick={handleOpenCard} />
        ))}
      </GridLayout>
      {loading ? <Loading /> : ""}
    </div>
  );
};
