import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
import { connect } from "react-redux";

import {
	BackFolder,
	Button,
	EmptyState,
	ErrorToast,
	FilterTagsBar,
	Icon,
	IconAction,
	ImageDragAndDrop,
	Loading,
	MainWrapper,
	Modal,
	SearchField,
	SearchTagsBar,
	TableList,
	Tabs,
	Toast,
	Tooltip,
} from "@ax/components";
import { galleryActions } from "@ax/containers/Gallery";
import { useBulkSelection, useIsDirty, useModal, usePermission, useResizable, useToast } from "@ax/hooks";
import type {
	IBulkAction,
	IFolder,
	IFolderTree,
	IGetFolderParams,
	IImage,
	IImageFolder,
	IQueryValue,
	IRootState,
	ISite,
} from "@ax/types";

import { DeleteFileModal, MoveItemModal, NewFolderModal, NotSavedModal } from "./atoms";
import Breadcrumb from "./Breadcrumb";
import BulkGridHeader from "./BulkGridHeader";
import BulkListHeader from "./BulkListHeader";
import FolderItem from "./FolderItem";
import FolderTree from "./FolderTree";
import GridItem from "./GridItem";
import { useFilterQuery, useSortedListStatus } from "./hooks";
import Orientation from "./ImageFilters/Orientation";
import SortBy from "./ImageFilters/SortBy";
import Type from "./ImageFilters/Type";
import UsageFilter from "./ImageFilters/Usage";
import ImageModal from "./ImageModal";
import ListItem from "./ListItem";
import UploadItem from "./UploadItem";
import { getSortedListStatus } from "./utils";

import * as S from "./style";

const MediaGallery = (props: IProps) => {
	const {
		currentFolderContent,
		currentFolderID,
		currentSiteInfo,
		getFolderContent,
		getFoldersTree,
		updateCurrentFolder,
		createNewFolder,
		deleteFolder,
		deleteImage,
		moveImage,
		updateDisplayMode,
		updateTab,
		downloadImages,
		uploadImage,
		breadcrumb,
		isLoading,
		isSaving,
		displayMode,
		selectedTab,
		foldersTree,
		isUploading,
	} = props;

	const initState: IImageFolder = { images: { items: [], totalItems: 0, currentPage: 1 }, folders: [] };
	const { images, folders } = currentFolderContent || initState;
	const { items, totalItems } = images;

	const itemsPerPage = 50;
	const firstPage = 1;
	const lastPage = Math.ceil(totalItems / itemsPerPage);
	const [page, setPage] = useState(firstPage);
	const [isBulkLoading, setIsBulkLoading] = useState(false);
	const [isPanelOpen, setPanelOpen] = useState(false);
	const [fileSelected, setFileSelected] = useState<IImage | null>(null);
	const [selectedFolder, setSelectedFolder] = useState<number | null>(currentFolderID || null);
	const imagesIds = items?.map((image) => image.id) || [];
	const [galleryItems, setGalleryItems] = useState<number[]>(imagesIds);
	const [galleryDelete, setGalleryDelete] = useState(true);
	const [progressItems, setProgressItems] = useState<IProgressState>({
		tab: selectedTab,
		folder: currentFolderID,
		items: [],
	});
	const [wrapperWidth, setWrapperWidth] = useState<number>();
	const [isLoadingMore, setIsLoadingMore] = useState(false);
	const tableRef = useRef<HTMLDivElement>(null);
	const contentRef = useRef<HTMLDivElement>(null);
	const wrapperRef = useRef<HTMLDivElement>(null);
	const { isOpen: isNewOpen, toggleModal: toggleNewModal } = useModal();
	const { isOpen: isUploadOpen, toggleModal: toggleUploadModal } = useModal();
	const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
	const { isOpen: isMoveOpen, toggleModal: toggleMoveModal } = useModal();
	const { isOpen: isSaveOpen, toggleModal: toggleSaveModal } = useModal();
	const { isOpen, toggleModal } = useModal();
	const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
	const [ref] = useResizable();

	const initFolderState = { name: "", folderID: currentFolderID };
	const [folderForm, setFolderForm] = useState<IFolderFormState>(initFolderState);
	const { setFiltersSelection, resetFilterQuery, filterValues, filterQuery } = useFilterQuery();
	const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
	const [searchQuery, setSearchQuery] = useState<string>("");
	const isSearching = searchQuery.length > 0;

	const initImageState: IImageFormState = { title: "", alt: "", tags: [] };
	const [fileForm, setFileForm] = useState(initImageState);
	const { isDirty, resetDirty } = useIsDirty(fileForm);

	const isSiteView = !!currentSiteInfo;
	const isTabGlobal = selectedTab === "global";
	const siteID: number | "global" = !isSiteView || isTabGlobal ? "global" : currentSiteInfo.id;
	const hasFolders = !!folders?.length;
	const isRoot = !breadcrumb?.length;
	const isGrid = displayMode === "grid";

	const allowedToAccessGlobalFromSite = usePermission("mediaGallery.accessToGlobalGalleryFromSite");

	const allowedToAddSiteFile = usePermission("mediaGallery.addImages");
	const allowedToAddGlobalFile = usePermission("global.mediaGallery.addGlobalImages");
	const allowedToAddGlobalFileFromSite = false;
	const allowedToAddFile = !isSiteView
		? allowedToAddGlobalFile
		: isTabGlobal
			? allowedToAddGlobalFileFromSite
			: allowedToAddSiteFile;

	const allowedToEditSiteFile = usePermission("mediaGallery.editImages");
	const allowedToEditGlobalFile = usePermission("global.mediaGallery.editGlobalImages");
	const allowedToEditGlobalFileFromSite = false;
	const allowedToEditFile = !isSiteView
		? allowedToEditGlobalFile
		: isTabGlobal
			? allowedToEditGlobalFileFromSite
			: allowedToEditSiteFile;

	const allowedToDeleteSiteFile = usePermission("mediaGallery.deleteImages");
	const allowedToDeleteGlobalFile = usePermission("global.mediaGallery.deleteGlobalImages");
	const allowedToDeleteGlobalFileFromSite = false;

	const allowedToDeleteFile = !isSiteView
		? allowedToDeleteGlobalFile
		: isTabGlobal
			? allowedToDeleteGlobalFileFromSite
			: allowedToDeleteSiteFile;

	const getParams = useCallback(() => {
		const params: IGetFolderParams = {
			siteID,
			folderID: currentFolderID,
			search: searchQuery,
			query: filterQuery,
			loading: !(isGrid && page > 1),
			thumbHeight: 188,
			pagination: true,
			page,
			itemsPerPage,
			infinite: isGrid && page > 1,
		};

		return params;
	}, [currentFolderID, searchQuery, filterQuery, siteID, page, isGrid]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useLayoutEffect(() => {
		return () => {
			updateCurrentFolder(null);
			updateTab("site");
			setPage(firstPage);
		};
	}, []);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		const handleGetContent = async () => {
			const params = getParams();
			await getFolderContent(params);
			setIsLoadingMore(false);
		};
		const handleGetTree = async () => await getFoldersTree(siteID);

		handleGetContent();
		handleGetTree();
		resetDirty();
	}, [getParams, selectedTab]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		const imagesIds: number[] = items?.map((image) => image.id) || [];
		setGalleryItems(imagesIds);
	}, [images]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		if (!foldersTree.length && isPanelOpen) {
			setPanelOpen(false);
		}
	}, [foldersTree]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		const handleResize = () => {
			if (wrapperRef.current) {
				setWrapperWidth(wrapperRef.current.offsetWidth);
			}
		};
		handleResize();

		window.addEventListener("resize", handleResize);
		return () => window.removeEventListener("resize", handleResize);
	}, [wrapperRef.current]);

	const onScroll = () => {
		if (contentRef.current && isGrid) {
			const { scrollTop, scrollHeight, clientHeight } = contentRef.current;
			if (
				scrollTop + clientHeight + 100 >= scrollHeight &&
				items.length < totalItems &&
				page < lastPage &&
				!isLoadingMore
			) {
				setIsLoadingMore(true);
				setPage((currentPage) => currentPage + 1);
			}
		}
	};

	const {
		resetBulkSelection,
		selectedItems,
		isSelected,
		areItemsSelected,
		checkState,
		addToBulkSelection,
		selectAllItems,
		setHoverCheck,
	} = useBulkSelection(imagesIds);

	const handleSelectedTab = (tab: "site" | "global") => {
		if (tab !== selectedTab) {
			setSearchQuery("");
			updateCurrentFolder(null);
			updateTab(tab);
			setPage(firstPage);
		}
	};

	const handleNewFolder = () => {
		setFolderForm(initFolderState);
		!isNewOpen && toggleNewModal();
	};

	const changeDisplayMode = (mode: "grid" | "list") => updateDisplayMode(mode);

	const selectItems = () => (checkState.isAllSelected ? resetBulkSelection() : selectAllItems());

	const handleBackClick = () => {
		const parentID = breadcrumb.length >= 2 ? breadcrumb[breadcrumb.length - 2].id : null;
		resetBulkSelection();
		setPage(firstPage);
		updateCurrentFolder(parentID);
	};

	const togglePanel = () => setPanelOpen(!isPanelOpen);

	const handleCreateNewFolder = async () => {
		const siteID: number | null = !isSiteView || isTabGlobal ? null : currentSiteInfo.id;
		const params = getParams();
		const isCreated = await createNewFolder(
			{
				site: siteID,
				folderName: folderForm.name,
				parentId: folderForm.folderID,
			},
			params,
		);
		if (isCreated) {
			isNewOpen && toggleNewModal();
			toggleToast("1 new folder created");
		}
	};

	const handleDeleteFolder = async (folder: IFolder) => {
		const params = getParams();
		const isDeleted = await deleteFolder(folder, params);
		if (isDeleted) {
			toggleToast("1 folder deleted");
		}
	};

	const handleClick = (file: IImage) => {
		setFileSelected(file);
		toggleModal();
	};

	const handleUpload = async (files: IImage[]) => {
		setFileSelected(files[0]);
		isUploadOpen && toggleUploadModal();
		toggleModal();
		const params = getParams();
		await getFolderContent(params);
	};

	const uploadMultipleFiles = async (files: File[]) => {
		try {
			let index = 0;
			while (files.length) {
				const handleProgress = (progress: number) => {
					setProgressItems((prevState) => ({
						...prevState,
						items: [...prevState.items.slice(0, index), progress, ...prevState.items.slice(index + 1)],
					}));
				};

				const file = files.shift();
				file && (await uploadImage(file, siteID || "global", handleProgress, true, currentFolderID));
				index = index + 1;
			}
		} catch (error) {
			console.log(error);
		}
	};

	const handleMultipleUpload = async (files: File[]) => {
		isUploadOpen && toggleUploadModal();

		const initialProgress = files.map(() => 0);
		setProgressItems({ tab: selectedTab, folder: currentFolderID, items: initialProgress });

		await uploadMultipleFiles(files);

		setProgressItems((prevState) => ({ ...prevState, items: [] }));

		updateTab(selectedTab);
		updateCurrentFolder(currentFolderID);

		const params = getParams();
		await getFolderContent(params);
	};

	const handleCloseModal = () => {
		if (isDirty) {
			toggleSaveModal();
		} else {
			resetFileModal();
		}
	};

	const resetFileModal = () => {
		setFileSelected(null);
		setGalleryItems(imagesIds);
		setGalleryDelete(true);
		resetDirty();
		toggleModal();
	};

	const handleDeleteFile = async (imageID: number) => {
		const params = getParams();
		const resetedParams = { ...params, page: firstPage, infinite: false, loading: true };
		const isDeleted = await deleteImage(imageID, resetedParams);
		if (isDeleted) {
			toggleToast("1 Image deleted");
			isOpen && handleCloseModal();
		}
	};

	const handleBulkDeleteFile = async () => {
		setIsBulkLoading(true);
		const params = getParams();
		const resetedParams = { ...params, page: firstPage, infinite: false, loading: true };
		const isDeleted = await deleteImage(selectedItems.all, resetedParams);
		if (isDeleted) {
			toggleToast(`${selectedItems.all.length} Image${selectedItems.all.length > 1 ? "s" : ""} deleted`);
			resetBulkSelection();
		}
		toggleDeleteModal();
		setIsBulkLoading(false);
	};

	const handleMoveImage = async (imageID: number, folderID: number | "root") => {
		setIsBulkLoading(true);
		const params = getParams();
		const resetedParams = { ...params, page: firstPage, infinite: false, loading: true };
		const isMoved = await moveImage(imageID, folderID, resetedParams);
		if (isMoved) {
			toggleToast("1 Image moved to a folder");
		}
		setIsBulkLoading(false);
	};

	const handleBulkMoveFile = async () => {
		setIsBulkLoading(true);
		const params = getParams();
		const resetedParams = { ...params, page: firstPage, infinite: false, loading: true };
		const isMoved = await moveImage(selectedItems.all, selectedFolder || "root", resetedParams);
		if (isMoved) {
			toggleMoveModal();
			toggleToast(`${selectedItems.all.length} Image${selectedItems.all.length > 1 ? "s" : ""} moved to a folder`);
			setSelectedFolder(0);
			resetBulkSelection();
		}
		setIsBulkLoading(false);
	};

	const handleBulkEditFile = () => {
		const currentFile = items.find((file: IImage) => file.id === selectedItems.all[0]);
		if (currentFile) {
			setGalleryItems(selectedItems.all);
			setFileSelected(currentFile);
			setGalleryDelete(false);
			toggleModal();
		}
	};

	const handleModalClose = () => {
		setSelectedFolder(0);
		isMoveOpen && toggleMoveModal();
	};

	const handleSelectFile = (id: number) => {
		const currentFile = items.find((file: IImage) => file.id === id);
		if (currentFile) {
			setFileSelected(currentFile);
		}
	};

	const handleDownloadBulk = async () => {
		setIsBulkLoading(true);
		const fileName = isSiteView ? `${currentSiteInfo.name}-images.zip` : "global-images.zip";
		await downloadImages(selectedItems.all, true, fileName);
		resetBulkSelection();
		setIsBulkLoading(false);
	};

	const handleUpdateCurrentFolder = (folderID: number | null) => {
		setSearchQuery("");
		resetBulkSelection();
		setPage(firstPage);
		updateCurrentFolder(folderID);
	};

	const handleDownload = async (imageID: number, fileName: string) => await downloadImages(imageID, false, fileName);

	const sortItems = (orderPointer: IQueryValue[], isAscending: boolean) => {
		setPage(firstPage);
		const sortedState = getSortedListStatus(orderPointer[0].value.toString(), isAscending);
		setSortedListStatus(sortedState);
		setFiltersSelection("order", orderPointer, isAscending);
	};

	const filterItems = (filterPointer: string, filtersSelected: IQueryValue[]) => {
		setPage(firstPage);
		setFiltersSelection(filterPointer, filtersSelected);
	};

	const handleSearch = (query: string) => {
		setSearchQuery(query);
		setPage(firstPage);
	};

	let bulkActions: IBulkAction[] = [];

	if (allowedToEditFile) {
		bulkActions = [
			{
				icon: "edit",
				text: "edit",
				action: handleBulkEditFile,
			},
			{
				icon: "change",
				text: "Move to",
				action: toggleMoveModal,
			},
		];
	}

	bulkActions = [
		...bulkActions,
		{
			icon: "download",
			text: "download",
			action: handleDownloadBulk,
		},
	];

	if (allowedToDeleteFile) {
		bulkActions = [
			...bulkActions,
			{
				icon: "delete",
				text: "delete",
				action: toggleDeleteModal,
			},
		];
	}

	const Header = (
		<BulkListHeader
			showBulk={areItemsSelected(imagesIds)}
			checkState={checkState}
			selectAllItems={selectItems}
			totalItems={totalItems}
			selectItems={selectItems}
			bulkActions={bulkActions}
			setHoverCheck={setHoverCheck}
			selectedItems={selectedItems}
			isLoading={isBulkLoading}
		/>
	);

	const isCurrentUploadingFolder = progressItems.tab === selectedTab && progressItems.folder === currentFolderID;

	const gridList = (
		<S.GridWrapper>
			{isCurrentUploadingFolder &&
				progressItems.items.map((progress: number, index: number) => (
					<UploadItem uploadPercentage={progress} grid={true} key={index} />
				))}
			{items?.map((image: IImage) => {
				const isItemSelected = isSelected(image.id);
				return (
					<GridItem
						image={image}
						isSelected={isItemSelected}
						onChange={addToBulkSelection}
						key={`${image.name}${image.id}`}
						onClick={handleClick}
						onDelete={handleDeleteFile}
						onMove={handleMoveImage}
						currentFolderID={currentFolderID}
						isAllowedToDelete={allowedToDeleteFile}
						isAllowedToEdit={allowedToEditFile}
						isAllowedToMove={!isRoot || (isRoot && (folders.length > 0 || isSearching))}
					/>
				);
			})}
		</S.GridWrapper>
	);

	const pagination = {
		setPage,
		itemsPerPage,
		totalItems,
		currPage: page,
	};

	const listTable = (
		<TableList
			tableHeader={Header}
			pagination={pagination}
			hasFixedHeader={true}
			tableRef={tableRef}
			className="no-padding"
		>
			<>
				{isCurrentUploadingFolder &&
					progressItems.items.map((progress: number, index: number) => (
						<UploadItem uploadPercentage={progress} grid={false} key={index} />
					))}
				{items?.map((image: IImage) => {
					const isItemSelected = isSelected(image.id);
					return (
						<ListItem
							image={image}
							isSelected={isItemSelected}
							onChange={addToBulkSelection}
							key={`${image.name}${image.id}`}
							onClick={handleClick}
							onDelete={handleDeleteFile}
							onMove={handleMoveImage}
							currentFolderID={currentFolderID}
							isAllowedToDelete={allowedToDeleteFile}
							isAllowedToEdit={allowedToEditFile}
							isAllowedToMove={!isRoot || (isRoot && (folders.length > 0 || isSearching))}
							hoverCheck={checkState.hoverCheck}
						/>
					);
				})}
			</>
		</TableList>
	);

	const rightButtonProps = allowedToAddFile
		? {
				label: "Upload",
				action: () => toggleUploadModal(),
				disabled: isUploading,
			}
		: undefined;

	const emptyProps = {
		message: allowedToAddFile ? (
			<>
				To start using images in your site, upload as many
				<br />
				images as you need
			</>
		) : (
			""
		),
		button: allowedToAddFile ? "Upload image" : undefined,
		action: () => toggleUploadModal(),
	};

	const emptySearchStateProps = {
		icon: "search",
		title: "Oh! No Results Found",
		message: "We couldn’t find what you are looking for. Please, try another search.",
	};

	const mainNewModalAction = {
		title: isSaving ? "Saving..." : "Create New Folder",
		onClick: () => handleCreateNewFolder(),
		disabled: folderForm.name.trim().length === 0 || isSaving,
	};

	const secondaryNewModalAction = { title: "Cancel", onClick: toggleNewModal };

	const mainDeleteModalAction = {
		title: isBulkLoading ? "Deleting" : "Delete",
		onClick: () => handleBulkDeleteFile(),
		disabled: isBulkLoading,
	};

	const secondaryDeleteModalAction = { title: "Cancel", onClick: toggleDeleteModal };

	const mainMoveModalAction = {
		title: "Move",
		onClick: () => handleBulkMoveFile(),
	};

	const secondaryMoveModalAction = { title: "Cancel", onClick: handleModalClose };

	const handleMainAction = () => {
		toggleSaveModal();
		resetFileModal();
	};

	const mainSaveModalAction = {
		title: "Yes, discard changes",
		onClick: () => handleMainAction(),
	};

	const secondarySaveModalAction = { title: "Cancel", onClick: toggleSaveModal };

	const foldersIcon = isPanelOpen ? <Icon name="closePanel" size="24" /> : <Icon name="openPanel" size="24" />;

	const tabs = ["site", "global"];

	const NewFolderButton = () =>
		(isSiteView && isTabGlobal) || !allowedToAddFile ? (
			<></>
		) : (
			<S.ButtonWrapper>
				<Button type="button" onClick={handleNewFolder} buttonStyle="line" icon="NewFolder">
					New Folder
				</Button>
			</S.ButtonWrapper>
		);

	const filters = (
		<S.Filters>
			<Orientation filterItems={filterItems} />
			<Type filterItems={filterItems} />
			<SortBy sortItems={sortItems} sortedState={sortedListStatus} />
			<UsageFilter filterItems={filterItems} value={filterValues.usage} />
		</S.Filters>
	);

	return (
		<MainWrapper backLink={false} title="Media Gallery" rightButton={rightButtonProps}>
			<S.Wrapper ref={wrapperRef}>
				<S.FolderPanel
					isOpen={isPanelOpen}
					ref={ref}
					style={{ width: isPanelOpen ? "240px" : "0" }}
					maxWidth={wrapperWidth}
				>
					<S.FolderPanelContent>
						<FolderTree
							folderID={currentFolderID || 0}
							onClick={handleUpdateCurrentFolder}
							title="Folders"
							createAction={allowedToAddFile ? handleNewFolder : undefined}
						/>
					</S.FolderPanelContent>
					<S.ResizeHandle className="resizer" />
				</S.FolderPanel>
				<S.ContentWrapper ref={contentRef} onScroll={onScroll}>
					<ErrorToast />
					<S.FiltersBar isSite={isSiteView && allowedToAccessGlobalFromSite}>
						{isSiteView && allowedToAccessGlobalFromSite && (
							<S.TabsWrapper>
								<Tabs tabs={tabs} active={selectedTab} setSelectedTab={handleSelectedTab} noMargins />
							</S.TabsWrapper>
						)}
						{!isSiteView && filters}
						<S.DisplayModeWrapper>
							<IconAction icon="Grid2" onClick={() => changeDisplayMode("grid")} active={displayMode === "grid"} />
							<IconAction icon="BulletList" onClick={() => changeDisplayMode("list")} active={displayMode === "list"} />
						</S.DisplayModeWrapper>
					</S.FiltersBar>
					<S.FiltersBar isSite={false}>
						{isSiteView && filters}
						<S.SearchWrapper>
							<SearchField onChange={handleSearch} placeholder="Search" value={searchQuery} focus={false} />
						</S.SearchWrapper>
					</S.FiltersBar>
					{isLoading ? (
						<Loading />
					) : (
						<S.FolderContent>
							<S.SearchTags>
								<SearchTagsBar query={searchQuery} setQuery={handleSearch} />
								<FilterTagsBar
									filters={filterValues}
									setFilters={setFiltersSelection}
									labels={{ orientation: "Orientation", format: "Media type", usage: "Usage" }}
									resetFilters={resetFilterQuery}
								/>
							</S.SearchTags>
							{!isRoot && <Breadcrumb breadcrumb={breadcrumb} onClick={handleUpdateCurrentFolder} />}
							{(hasFolders || !isRoot) && (
								<S.SectionWrapper>
									<S.SectionHeader>
										<S.SectionTitle>
											<div>Folders</div>
											<S.FoldersIconWrapper onClick={togglePanel}>
												<Tooltip content="Open folder panel">{foldersIcon}</Tooltip>
											</S.FoldersIconWrapper>
										</S.SectionTitle>
										<NewFolderButton />
									</S.SectionHeader>
									<S.FoldersWrapper>
										{!isRoot && <BackFolder onClick={handleBackClick} />}
										<S.FoldersGrid>
											{folders.map((folder: IFolder) => (
												<FolderItem
													folder={folder}
													onClick={handleUpdateCurrentFolder}
													onDelete={handleDeleteFolder}
													key={`${folder.folderName}${folder.id}`}
													toggleToast={toggleToast}
													isAllowedToDelete={allowedToDeleteFile}
													isAllowedToEdit={allowedToEditFile}
													isAllowedToMove={!isRoot || (isRoot && (folders.length > 1 || isSearching))}
													getParams={getParams}
												/>
											))}
										</S.FoldersGrid>
									</S.FoldersWrapper>
								</S.SectionWrapper>
							)}
							<S.BigSectionWrapper>
								<S.SectionHeader>
									{totalItems > 0 && <S.SectionTitle>Media</S.SectionTitle>}
									{totalItems > 0 && isGrid && (
										<BulkGridHeader
											showBulk={areItemsSelected(imagesIds)}
											checkState={checkState}
											selectAllItems={selectItems}
											totalItems={totalItems}
											selectItems={selectItems}
											bulkActions={bulkActions}
											selectedItems={selectedItems}
											isLoading={isBulkLoading}
										/>
									)}
									{!hasFolders && isRoot && !isSearching && <NewFolderButton />}
								</S.SectionHeader>
								{(totalItems > 0 || progressItems.items.length > 0) && (
									<S.DocumentsWrapper>{isGrid ? gridList : listTable}</S.DocumentsWrapper>
								)}
								{totalItems === 0 && progressItems.items.length === 0 && !hasFolders && (
									<S.EmptyStateWrapper data-testid="empty-state" margin={!isRoot}>
										{isSearching && <EmptyState {...emptySearchStateProps} />}
										{!isSearching && isRoot && <EmptyState {...emptyProps} />}
									</S.EmptyStateWrapper>
								)}
							</S.BigSectionWrapper>
						</S.FolderContent>
					)}
				</S.ContentWrapper>
			</S.Wrapper>
			{isNewOpen && (
				<NewFolderModal
					isOpen={isNewOpen}
					toggleModal={toggleNewModal}
					mainModalAction={mainNewModalAction}
					secondaryModalAction={secondaryNewModalAction}
					form={folderForm}
					setForm={setFolderForm}
				/>
			)}
			<Modal isOpen={isUploadOpen} hide={toggleUploadModal} size="XL" title="Upload media">
				{isUploadOpen && (
					<ImageDragAndDrop
						folderID={currentFolderID}
						handleUpload={handleUpload}
						handleMultipleUpload={handleMultipleUpload}
						siteID={siteID}
						getParams={getParams}
					/>
				)}
			</Modal>
			<Modal isOpen={isOpen} hide={handleCloseModal} size="XL" title="Image details">
				{isOpen && fileSelected && (
					<ImageModal
						image={fileSelected}
						onDelete={handleDeleteFile}
						items={galleryItems}
						setFile={handleSelectFile}
						activeDelete={galleryDelete && allowedToDeleteFile}
						setFileSelected={setFileSelected}
						isAllowedToEdit={allowedToEditFile}
						handleDownload={handleDownload}
						form={fileForm}
						setForm={setFileForm}
						isDirty={isDirty}
						resetDirty={resetDirty}
						getParams={getParams}
					/>
				)}
			</Modal>
			{isDeleteOpen && (
				<DeleteFileModal
					isOpen={isDeleteOpen}
					toggleModal={toggleDeleteModal}
					mainModalAction={mainDeleteModalAction}
					secondaryModalAction={secondaryDeleteModalAction}
					title="these images"
				/>
			)}
			{isMoveOpen && (
				<MoveItemModal
					isOpen={isMoveOpen}
					toggleModal={handleModalClose}
					mainModalAction={mainMoveModalAction}
					secondaryModalAction={secondaryMoveModalAction}
					folder={selectedFolder}
					setFolder={setSelectedFolder}
				/>
			)}
			{isSaveOpen && (
				<NotSavedModal
					isOpen={isSaveOpen}
					toggleModal={toggleSaveModal}
					mainModalAction={mainSaveModalAction}
					secondaryModalAction={secondarySaveModalAction}
				/>
			)}
			{isVisible && <Toast setIsVisible={setIsVisible} message={toastState} />}
		</MainWrapper>
	);
};

interface IProps {
	isLoading: boolean;
	isSaving: boolean;
	currentFolderContent: IImageFolder | null;
	currentFolderID: number | null;
	currentSiteInfo: ISite | null;
	breadcrumb: IFolderTree[];
	displayMode: "grid" | "list";
	selectedTab: "site" | "global";
	foldersTree: IFolderTree[];
	isUploading: boolean;
	getFolderContent(params: IGetFolderParams): Promise<void>;
	getFoldersTree(siteID: number | "global"): Promise<void>;
	updateCurrentFolder(folderID: number | null): void;
	createNewFolder(
		data: { folderName: string; site: number | null; parentId: number | null },
		params: IGetFolderParams,
	): Promise<boolean>;
	deleteFolder(folder: IFolder, params: IGetFolderParams): Promise<boolean>;
	deleteImage(imageID: number | number[], params: IGetFolderParams): Promise<boolean>;
	moveImage(imageID: number | number[], folderID: number | "root", params: IGetFolderParams): Promise<boolean>;
	updateDisplayMode(displayMode: "grid" | "list"): Promise<void>;
	updateTab(tab: "site" | "global"): Promise<void>;
	downloadImages(imageID: number | number[], zip: boolean, fileName?: string): Promise<void>;
	uploadImage: (
		imageFiles: File | File[],
		site: number | string,
		setProgress?: (progress: number) => void,
		visible?: boolean,
		folderID?: number | null,
	) => Promise<IImage | null>;
}

export interface IFolderFormState {
	name: string;
	folderID: number | null;
}

export interface IImageFormState {
	title: string;
	alt: string;
	tags: string[];
}

interface IProgressState {
	tab: "global" | "site";
	folder: number | null;
	items: number[];
}

const mapDispatchToProps = {
	getSiteImages: galleryActions.getSiteImages,
	getFolderContent: galleryActions.getFolderContent,
	getFoldersTree: galleryActions.getFoldersTree,
	updateCurrentFolder: galleryActions.updateCurrentFolder,
	createNewFolder: galleryActions.createNewFolder,
	deleteFolder: galleryActions.deleteFolder,
	deleteImage: galleryActions.deleteImage,
	moveImage: galleryActions.moveImage,
	updateDisplayMode: galleryActions.updateDisplayMode,
	updateTab: galleryActions.updateTab,
	downloadImages: galleryActions.downloadImages,
	uploadImage: galleryActions.uploadImage,
};

const mapStateToProps = (state: IRootState) => ({
	isLoading: state.app.isLoading,
	isSaving: state.app.isSaving,
	currentFolderContent: state.gallery.currentFolderContent,
	currentFolderID: state.gallery.currentFolderID,
	breadcrumb: state.gallery.breadcrumb,
	currentSiteInfo: state.sites.currentSiteInfo,
	displayMode: state.gallery.displayMode,
	selectedTab: state.gallery.selectedTab,
	foldersTree: state.gallery.foldersTree,
	isUploading: state.gallery.isUploading,
});

export default connect(mapStateToProps, mapDispatchToProps)(MediaGallery);
