import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { BEM_CLASS, SSmallArtistsSection } from './s-small-artists-section';
import { ArtistRosterItem, ArtistRosterProject, ArtistTeam } from 'backend-api/models';
import { bem } from 'utils/bem';
import { H4 } from 'common/components/typography';
import { Icon } from 'common/components/icon';
import { LoadableData } from 'common/types';
import { RowLoader, SmallArtistItem, TitleLoader } from './components';
import { AnimatePresence, motion } from 'framer-motion';
import { ARTIST_PAGINATION_STEP, COLUMN_COUNT, GRID_ITEM_GAP } from './constants';
import { ResponsiveContainer } from 'common/components/sidebar-form/responsive-container';
import { ArtistRosterExpansionContainer } from 'projects/containers/artist-roster-expansion';
import { GetExpansionProjectsPayload } from 'projects/types';
import { useArtistRosterExpansion } from 'projects/hooks/use-artist-roster-expansion';
import { Button } from 'common/components/button';

interface Props {
  items: ArtistRosterItem[];
  isExpanded?: boolean;
  isLoading?: boolean;
  canExpandItem?: boolean;
  onExpand?(): void;
  title: string;
  className?: string;
  artistTeamLoadable?: LoadableData<ArtistTeam[]>;
  projectsLoadable?: LoadableData<ArtistRosterProject[]>;
  getArtistTeams(id: string): void;
  getExpansionProjects(payload: GetExpansionProjectsPayload): void;
  expandedArtistId?: string;
  onItemExpand?(id?: string): void;
  paginationEnabled?: boolean;
}

const classes = bem(BEM_CLASS);

const expandAnimationProps = {
  initial: { height: 0, width: '100%', overflow: 'hidden', opacity: 1 },
  exit: { height: 0, opacity: 0 },
  animate: { height: 'unset', opacity: 1 },
  transition: { type: 'spring', damping: 10, mass: 0.3, stiffness: 70, when: 'beforeChildren' },
};

const artistGridTransition = {
  type: 'tween',
  duration: 0.2,
  when: 'beforeChildren',
};

export const SmallArtistsSection = React.memo(
  ({
    title,
    isExpanded,
    items,
    onExpand,
    className,
    isLoading,
    canExpandItem,
    artistTeamLoadable,
    projectsLoadable,
    getArtistTeams,
    getExpansionProjects,
    expandedArtistId,
    onItemExpand,
    paginationEnabled,
  }: Props) => {
    const [showingArtist, setShowingArtist] = useState(ARTIST_PAGINATION_STEP);
    const getIndex = useCallback((artistId?: string) => items.findIndex(item => item.artist.id === artistId), [items]);
    const gridRef = useRef<HTMLDivElement>(null);

    const { expansionRow, arrowPosition, onItemClick, onCollapseFinish } = useArtistRosterExpansion({
      gridElement: gridRef.current,
      expandedArtistId,
      items,
      onItemExpand,
      gridGap: GRID_ITEM_GAP,
      columnCount: COLUMN_COUNT,
      rowHeight: 49,
    });

    const shouldShowDividerForItem = useCallback(
      (index: number) => {
        const currentRow = Math.floor(index / COLUMN_COUNT);
        const isCurrentRowExpanded = (expansionRow || 0) - 2 === currentRow && expandedArtistId !== undefined;
        const maxRows = Math.floor(items.length / COLUMN_COUNT);

        return !isCurrentRowExpanded && maxRows !== currentRow;
      },
      [items.length, expandedArtistId, expansionRow]
    );

    const expandedArtist = useMemo(() => items[getIndex(expandedArtistId)]?.artist, [
      expandedArtistId,
      getIndex,
      items,
    ]);

    const displayedArtists = useMemo(() => (paginationEnabled ? items.slice(0, showingArtist) : items), [
      items,
      showingArtist,
      paginationEnabled,
    ]);
    const nextStep = useMemo(() => Math.min(ARTIST_PAGINATION_STEP, Math.max(0, items.length - showingArtist)), [
      items.length,
      showingArtist,
    ]);

    useEffect(() => {
      if (!isExpanded) {
        setShowingArtist(ARTIST_PAGINATION_STEP);
      }
    }, [isExpanded]);

    const onPaginationClick = useCallback(() => setShowingArtist(showingArtist + nextStep), [nextStep, showingArtist]);

    return (
      <SSmallArtistsSection className={className} expansionRow={expansionRow}>
        <ResponsiveContainer>
          {isLoading ? (
            <TitleLoader />
          ) : (
            <div className={classes('title-container')}>
              <Icon
                className={classes('expand-icon')}
                name={isExpanded ? 'collapse' : 'expand'}
                color="black"
                onClick={onExpand}
              />
              <H4>
                {title} ({items.length})
              </H4>
            </div>
          )}
          {isExpanded && isLoading && <RowLoader />}
        </ResponsiveContainer>
        <AnimatePresence exitBeforeEnter presenceAffectsLayout>
          {isExpanded && !isLoading && (
            <motion.div {...expandAnimationProps}>
              <ResponsiveContainer>
                <motion.div
                  layout
                  ref={gridRef}
                  className={classes('artists-container')}
                  layoutId="artists-container-grid"
                  transition={artistGridTransition}
                >
                  <AnimatePresence initial={false} presenceAffectsLayout>
                    {displayedArtists.map((item, index) => (
                      <SmallArtistItem
                        key={item.artist.id}
                        item={item}
                        onClick={() => onItemClick(item.artist.id)}
                        canExpand={canExpandItem}
                        isExpanded={item.artist.id === expandedArtistId}
                        shouldShowDivider={shouldShowDividerForItem(index)}
                      />
                    ))}
                  </AnimatePresence>
                  {artistTeamLoadable && projectsLoadable && (
                    <ArtistRosterExpansionContainer
                      className={classes('expanded-section')}
                      isExpanded={expandedArtistId !== undefined}
                      artist={expandedArtist}
                      artistTeamLoadable={artistTeamLoadable}
                      projectsLoadable={projectsLoadable}
                      arrowPosition={arrowPosition}
                      onCollapseFinish={onCollapseFinish}
                      getArtistTeams={getArtistTeams}
                      getExpansionProjects={getExpansionProjects}
                    />
                  )}
                  {nextStep !== 0 && paginationEnabled && (
                    <Button
                      className={classes('pagination-button')}
                      variant="secondary-white"
                      onClick={onPaginationClick}
                    >
                      {`Show ${nextStep} more`}
                    </Button>
                  )}
                </motion.div>
              </ResponsiveContainer>
            </motion.div>
          )}
        </AnimatePresence>
      </SSmallArtistsSection>
    );
  }
);
