import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { useEventListener } from '@devesharp/react-hooks';
import { FormHandles } from '@unform/core';
import { useImmer } from 'use-immer';
import { ITagFilterRef } from '../../TagsFilters';
import { CardListingContainer } from './CardListingContainer';
import { FiltersContainer } from './FiltersContainer';
import { HeaderContainer } from './HeaderContainer';
import { IPageListingProps } from './PageListing.interface';
import * as S from './PageListing.style';
import { PageListingContext } from './PageListingContext';
import { SubHeaderContainer } from './SubHeaderContainer';

export const PageListing: React.FunctionComponent<IPageListingProps> = (props) => {
   const {
      viewList,
      title,
      tabs,
      sortOptions,
      tagsFilters,
      renderResource,
      renderResourceSkeleton,
      limit = 20,
   } = props;

   const listingElRef = useRef<any>();

   useEffect(
      () =>
         viewList.registerOnSearch(() => {
            listingElRef.current.scrollTop = 0;
         }),
      [],
   );

   const handleFilters = useCallback(function handleFilters(data: any) {
      viewList.setFilters(() => data);
   }, []);

   const clearFilters = useCallback(function clearFilters() {
      viewList.setFilters(() => ({}));
   }, []);

   const changePage = useCallback((page) => {
      viewList.setPage(page);
   }, []);

   /**
    * Filters
    */
   const [filterMobileOpen, setFilterMobileOpen] = useState<boolean>(false);
   const openFilters = useCallback(() => {
      setFilterMobileOpen(true);
      if (viewList.history) {
         viewList.history.push({
            search: window.location.search,
            hash: '#filter',
         });
      } else {
         window.location.hash = 'filter';
      }
   }, []);

   const closeFilters = useCallback(() => {
      setFilterMobileOpen(false);

      if (window.location.hash === '#filter') {
         if (viewList.history) {
            viewList.history.back();
         } else {
            window.history.back();
         }
      }
   }, []);

   useEffect(() => {
      if (window.location.hash === '#filter') {
         window.location.replace('');
      }
   }, []);

   useEventListener('hashchange', function hashchange() {
      if (window.location.hash === '#filter') {
         setFilterMobileOpen(true);
      } else {
         setFilterMobileOpen(false);
      }
   });

   //
   const [filtersTemp, setFiltersTemp] = useImmer<any>(viewList.filters);

   const handleFiltersMobile = useCallback(function handleFiltersMobile(data: any) {
      setFiltersTemp(() => data);
   }, []);

   const clearFiltersMobile = useCallback(function clearFiltersMobile() {
      closeFilters();
      viewList.setFilters(() => ({}));
   }, []);

   const applyFilters = useCallback(
      function applyFilters() {
         viewList.setFilters(() => filtersTemp, { replaceUrl: true });
         setFilterMobileOpen(false);
      },
      [filtersTemp],
   );

   const page = viewList.filters.page ?? 1;
   let pageCountStart = (page - 1) * 20 + 1;
   pageCountStart = viewList.resourcesTotal ? pageCountStart : 0;
   let pageCountEnd = (page - 1) * 20 + 20;
   pageCountEnd = pageCountEnd > viewList.resourcesTotal ? viewList.resourcesTotal : pageCountEnd;

   const currentPage = (viewList.filters.offset ?? 0) / limit + 1;

   const showCardsSkeleton = viewList.searching || viewList.loading;
   const showCards = viewList.started && !viewList.searching;

   const formSortRef = useRef<FormHandles>();
   const tagsFiltersRef = useRef<ITagFilterRef>();
   const providerValue = {
      ...viewList,
      title,
      tabs,
      sortOptions,
      handleFilters,
      clearFilters,
      pageCountStart,
      pageCountEnd,
      currentPage,
      applyFilters,
      changePage,
      formSortRef,
      showCardsSkeleton,
      showCards,
      tagsFilters,
      tagsFiltersRef,
      renderResource,
      openFilters,
      closeFilters,
      handleFiltersMobile,
      clearFiltersMobile,
      filterMobileOpen,
      renderResourceSkeleton,
      FiltersComponent: props.FiltersComponent,
   };

   return (
      <PageListingContext.Provider value={providerValue}>
         <S.Container>
            <div className="col-filters">
               <FiltersContainer />
            </div>

            <div className="col-listing" ref={listingElRef}>
               <HeaderContainer />
               <SubHeaderContainer />
               <CardListingContainer />
            </div>
         </S.Container>
      </PageListingContext.Provider>
   );
};
