import { noop } from 'lodash-es';
import {
  Dispatch,
  SetStateAction,
  useCallback,
  useEffect,
  useMemo,
  useRef,
} from 'react';
import { useLocalStorage, useSessionStorage } from 'usehooks-ts';

import { createContext, useContextSelector } from '@/hooks/useContextSelector';

import { PanelSize } from '../panelSystem/PanelSystem';
import { oneFRPanelSize } from './StudioPanelUtilities';
import makePanelSize from './makePanelSize';

export type LayoutMode = 'horizontal' | 'vertical';
export type LibrarySessionMode = 'library' | 'session' | 'both';

export const COLLAPSED_PANEL_SIZE = 48;

export default function useStudioLayoutManager(
  showNav: boolean,
  setShowNav: Dispatch<SetStateAction<boolean>>
) {
  const [layoutMode, setLayoutMode] = useLocalStorage<LayoutMode>(
    'aug-4-2025-studio-layout-mode',
    'horizontal'
  );

  const [userCreatePanelSize, setUserCreatePanelSize] =
    useLocalStorage<PanelSize>(
      'aug-4-2025-studio-create-panel-size',
      makePanelSize(450)
    );

  const [horizontalUserLibraryPanelSize, setHorizontalUserLibraryPanelSize] =
    useLocalStorage<PanelSize>(
      'aug-4-2025-studio-horizontal-library-panel-size',
      makePanelSize(450)
    );

  const [horizontalCreatePanelExpanded, setHorizontalCreatePanelExpanded] =
    useLocalStorage('aug-4-2025-studio-horizontal-expand-create-panel', false);

  const [horizontalLibrarySessionMode, setHorizontalLibrarySessionMode] =
    useLocalStorage<LibrarySessionMode>(
      'aug-4-2025-studio-horizontal-library-session-mode',
      'session'
    );

  const cycleLayoutMode = useCallback(() => {
    setLayoutMode((prev) =>
      prev === 'horizontal' ? 'vertical' : 'horizontal'
    );
  }, []);

  const createPanelExpanded = useMemo(() => {
    return layoutMode === 'horizontal' ? horizontalCreatePanelExpanded : true;
  }, [layoutMode, horizontalCreatePanelExpanded]);

  const libraryPanelExpanded = useMemo(() => {
    return layoutMode === 'horizontal'
      ? horizontalLibrarySessionMode !== 'session'
      : true;
  }, [layoutMode, horizontalLibrarySessionMode]);

  const sessionPanelExpanded = useMemo(() => {
    return layoutMode === 'horizontal'
      ? horizontalLibrarySessionMode !== 'library'
      : true;
  }, [layoutMode, horizontalLibrarySessionMode]);

  const setCreatePanelExpanded = useCallback(
    (expanded: SetStateAction<boolean>) => {
      if (layoutMode === 'horizontal') {
        setHorizontalCreatePanelExpanded(expanded);
      }
    },
    [layoutMode, setHorizontalCreatePanelExpanded]
  );

  const setLibraryPanelExpanded = useCallback(
    (expanded: SetStateAction<boolean>) => {
      if (layoutMode === 'horizontal') {
        if (typeof expanded === 'boolean') {
          setHorizontalLibrarySessionMode(expanded ? 'both' : 'session');
        } else {
          setHorizontalLibrarySessionMode((prev) => {
            const isExpanded = prev !== 'session';
            const newExpanded = expanded(isExpanded);
            return newExpanded ? 'both' : 'session';
          });
        }
      }
    },
    [layoutMode, setHorizontalLibrarySessionMode]
  );

  const setSessionPanelExpanded = useCallback(
    (expanded: SetStateAction<boolean>) => {
      if (layoutMode === 'horizontal') {
        if (typeof expanded === 'boolean') {
          setHorizontalLibrarySessionMode(expanded ? 'both' : 'library');
        } else {
          setHorizontalLibrarySessionMode((prev) => {
            const isExpanded = prev !== 'library';
            const newExpanded = expanded(isExpanded);
            return newExpanded ? 'both' : 'library';
          });
        }
      }
    },
    [layoutMode, setHorizontalLibrarySessionMode]
  );

  const [focusedObjectPanelExpanded, setFocusedObjectPanelExpandedState] =
    useLocalStorage('aug-4-2025-focused-object-sidebar-expanded', true);

  const setFocusedObjectPanelExpanded = useCallback(
    (expanded: SetStateAction<boolean>) => {
      if (layoutMode === 'horizontal') {
        setFocusedObjectPanelExpandedState(expanded);
      }
    },
    [layoutMode, setFocusedObjectPanelExpandedState]
  );

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (
        document.activeElement instanceof HTMLTextAreaElement ||
        document.activeElement instanceof HTMLInputElement ||
        (document.activeElement instanceof HTMLElement &&
          document.activeElement.getAttribute('contenteditable') === 'true')
      ) {
        return;
      }

      if (e.key === '`') {
        cycleLayoutMode();
      }

      if (!e.ctrlKey && !e.metaKey) {
        if (e.key === '4' && layoutMode === 'horizontal') {
          setFocusedObjectPanelExpanded((prev) => !prev);
        } else if (e.key === '3' && layoutMode === 'horizontal') {
          if (libraryPanelExpanded && !sessionPanelExpanded) {
            setHorizontalLibrarySessionMode('both');
          } else if (sessionPanelExpanded) {
            setHorizontalLibrarySessionMode('library');
          }
        } else if (e.key === '2' && layoutMode === 'horizontal') {
          if (sessionPanelExpanded && !libraryPanelExpanded) {
            setHorizontalLibrarySessionMode('both');
          } else if (libraryPanelExpanded) {
            setHorizontalLibrarySessionMode('session');
          }
        } else if (e.key === '1' && layoutMode === 'horizontal') {
          setHorizontalCreatePanelExpanded(!horizontalCreatePanelExpanded);
        }
      }
    };

    window.addEventListener('keydown', handleKeyDown);

    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [
    cycleLayoutMode,
    setFocusedObjectPanelExpanded,
    setCreatePanelExpanded,
    setLibraryPanelExpanded,
    setSessionPanelExpanded,
    createPanelExpanded,
    libraryPanelExpanded,
    sessionPanelExpanded,
    horizontalCreatePanelExpanded,
    setHorizontalCreatePanelExpanded,
    setHorizontalLibrarySessionMode,
    setFocusedObjectPanelExpandedState,
  ]);

  const createPanelSize = useMemo(() => {
    return createPanelExpanded
      ? userCreatePanelSize
      : makePanelSize(COLLAPSED_PANEL_SIZE);
  }, [createPanelExpanded, userCreatePanelSize]);

  const libraryPanelSize = useMemo(() => {
    return libraryPanelExpanded
      ? sessionPanelExpanded
        ? horizontalUserLibraryPanelSize
        : oneFRPanelSize
      : makePanelSize(COLLAPSED_PANEL_SIZE);
  }, [
    libraryPanelExpanded,
    sessionPanelExpanded,
    horizontalUserLibraryPanelSize,
  ]);

  const sessionPanelSize = useMemo(() => {
    return sessionPanelExpanded
      ? oneFRPanelSize
      : makePanelSize(COLLAPSED_PANEL_SIZE);
  }, [sessionPanelExpanded, horizontalUserLibraryPanelSize]);

  const createPanelMinSizePx = useMemo(() => {
    return createPanelExpanded ? 368 : COLLAPSED_PANEL_SIZE;
  }, [createPanelExpanded]);

  const libraryPanelMinSizePx = useMemo(() => {
    return libraryPanelExpanded ? 368 : COLLAPSED_PANEL_SIZE;
  }, [libraryPanelExpanded]);

  const sessionPanelMinSizePx = useMemo(() => {
    return sessionPanelExpanded ? 368 : COLLAPSED_PANEL_SIZE;
  }, [sessionPanelExpanded]);

  const [verticalTopPanelSize, setVerticalTopPanelSize] =
    useLocalStorage<PanelSize>(
      'aug-4-2025-studio-vertical-top-panel-size',
      makePanelSize(500)
    );

  const [contextualBarExpanded, setContextualBarExpanded] = useSessionStorage(
    'aug-4-2025-studio-contextual-bar-expanded',
    false
  );

  // added so that we can log dimensions of panels
  const createPanelWrapperRef = useRef<HTMLDivElement>(null);
  const libraryPanelWrapperRef = useRef<HTMLDivElement>(null);
  const sessionPanelWrapperRef = useRef<HTMLDivElement>(null);
  const focusedObjectPanelWrapperRef = useRef<HTMLDivElement>(null);

  return {
    layoutMode,
    cycleLayoutMode,

    createPanelExpanded,
    libraryPanelExpanded,
    sessionPanelExpanded,
    focusedObjectPanelExpanded,

    setCreatePanelExpanded,
    setLibraryPanelExpanded,
    setSessionPanelExpanded,
    setFocusedObjectPanelExpanded,

    createPanelSize,
    libraryPanelSize,
    sessionPanelSize,

    createPanelMinSizePx,
    libraryPanelMinSizePx,
    sessionPanelMinSizePx,

    setUserCreatePanelSize,
    setHorizontalUserLibraryPanelSize,

    verticalTopPanelSize,
    setVerticalTopPanelSize,

    contextualBarExpanded,
    setContextualBarExpanded,

    showNav,
    setShowNav,

    createPanelWrapperRef,
    libraryPanelWrapperRef,
    sessionPanelWrapperRef,
    focusedObjectPanelWrapperRef,
  };
}

export const useExpandCreatePanel = () => {
  const setCreatePanelExpanded = useContextSelector(
    StudioLayoutManagerContext,
    (context) => context?.setCreatePanelExpanded ?? noop
  );
  const expandCreatePanel = useCallback(
    (expanded: boolean = true) => {
      setCreatePanelExpanded(expanded);
    },
    [setCreatePanelExpanded]
  );
  return expandCreatePanel;
};

export const StudioLayoutManagerContext = createContext<ReturnType<
  typeof useStudioLayoutManager
> | null>(null);
