import { NOOP, ZERO } from '@/constants/common';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { mapOpenedMapsSelector } from '@/redux/map/map.selectors';
import { openMapAndSetActive, setActiveMap, setMapPosition } from '@/redux/map/map.slice';
import { closeModal, setOverviewImageId } from '@/redux/modal/modal.slice';
import { currentModelIdSelector, modelsDataSelector } from '@/redux/models/models.selectors';
import { projectOverviewImagesSelector } from '@/redux/project/project.selectors';
import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
import { MapModel, OverviewImageLink, OverviewImageLinkModel } from '@/types/models';
import { getSearchData } from '@/redux/search/search.thunks';
import { openSearchDrawerWithSelectedTab } from '@/redux/drawer/drawer.slice';
import {
  OverviewImageLinkImageHandler,
  OverviewImageLinkModelHandler,
  OverviewImageLinkSearchHandler,
} from '../OverviewImageModal.types';

interface UseOverviewImageLinkActionsResult {
  handleLinkClick(link: OverviewImageLink): void;
}

export const useOverviewImageLinkActions = (): UseOverviewImageLinkActionsResult => {
  const dispatch = useAppDispatch();
  const openedMaps = useAppSelector(mapOpenedMapsSelector);
  const models = useAppSelector(modelsDataSelector);
  const overviewImages = useAppSelector(projectOverviewImagesSelector);
  const currentMapModelId = useAppSelector(currentModelIdSelector);

  const checkIfImageIsAvailable = (imageId: number): boolean =>
    overviewImages.some(image => image.idObject === imageId);

  const checkIfMapAlreadyOpened = (modelId: number): boolean =>
    openedMaps.some(map => map.modelId === modelId);

  const getModelById = (modelId: number): MapModel | undefined =>
    models.find(map => map.idObject === modelId);

  const handleOpenMap = (model: MapModel): void => {
    const modelId = model.idObject;
    const isMapOpened = checkIfMapAlreadyOpened(modelId);

    if (currentMapModelId !== modelId) {
      PluginsEventBus.dispatchEvent('onSubmapClose', currentMapModelId);
      PluginsEventBus.dispatchEvent('onSubmapOpen', modelId);
    }
    if (isMapOpened) {
      dispatch(setActiveMap({ modelId }));
      return;
    }

    dispatch(openMapAndSetActive({ modelId, modelName: model.name }));
  };

  const handleSetMapPosition = (link: OverviewImageLinkModel, model: MapModel): void => {
    const zoom = link.zoomLevel + model.minZoom;
    const { x } = link.modelPoint;
    const { y } = link.modelPoint;

    dispatch(
      setMapPosition({
        x,
        y,
        z: zoom,
      }),
    );
  };

  const onSubmapClick: OverviewImageLinkModelHandler = link => {
    const modelId = link.modelLinkId;
    const model = getModelById(modelId);
    if (!model) {
      return;
    }

    handleOpenMap(model);
    handleSetMapPosition(link, model);
    dispatch(closeModal());
  };

  const onSearchClick: OverviewImageLinkSearchHandler = link => {
    const { query } = link;

    const searchValues = query.split(',');
    dispatch(getSearchData({ searchQueries: searchValues, isPerfectMatch: false }));
    dispatch(openSearchDrawerWithSelectedTab(searchValues[ZERO]));

    dispatch(closeModal());
  };

  const onImageClick: OverviewImageLinkImageHandler = link => {
    const isImageAvailable = checkIfImageIsAvailable(link.imageLinkId);
    if (!isImageAvailable) {
      return;
    }

    dispatch(setOverviewImageId(link.imageLinkId));
  };

  const handleLinkClick: UseOverviewImageLinkActionsResult['handleLinkClick'] = link => {
    const isImageLink = 'imageLinkId' in link;
    const isModelLink = 'modelLinkId' in link;
    const isSearchLink = 'query' in link;

    if (isImageLink) {
      return onImageClick(link);
    }

    if (isModelLink) {
      return onSubmapClick(link);
    }

    if (isSearchLink) {
      return onSearchClick(link);
    }

    return NOOP();
  };

  return {
    handleLinkClick,
  };
};