import React, { ReactElement, useEffect, useRef } from 'react';
import { registerTabsListeners } from '../chrome/chromeTabsListeners';
import store from '../store/store';

import { loadPrefsFromDB } from '../db/prefsLoader';
import { shouldIgnore } from '../db/urlNormalizationPrefs';
import { initializeSearchIndex } from '../services/pageSearchIndex';

// Initialize on app start (both fire-and-forget; search falls back to full scan until ready)
loadPrefsFromDB();
initializeSearchIndex();

import './Main.less';

import { useAppDispatch, useAppSelector } from '../store/hooks';

import {
  clearSelection,
  SEARCH_TAB_INDEX,
  selectSearchInput,
  selectTabIndex,
  setSearchInput,
  setTabIndex,
} from '../store/uiSlice';
import Windows from './windows/Windows';
import { selectTabsCount, selectWindowsCount, updateWindowsAsync } from '../store/windowsSlice';
import { fetchStashCount, fetchFlagCount, fetchUntaggedCount, fetchAllCount, fetchPendingTodosCount } from '../db/pages';
import TodoView from './todo/TodoView';
import { useLiveQuery } from 'dexie-react-hooks';
import { getTabvanaWindowId } from '../db/prefs';
import SearchResult from './SearchResult';
import { faCartShopping, faEarth, faEye, faFlag, faQuestion } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import FlexView from './flexView/FlexView';
import '@fontsource/inter';
import {
  CssBaseline,
  CssVarsProvider,
  Input,
  ListItemDecorator,
  Sheet,
  Tab,
  TabList,
  TabPanel,
  Tabs,
} from '@mui/joy';
import GlobalButtons from './GlobalButtons';
import { fetchTags, fetchTagsCount } from '../db/tags';
import { FlagTag, StashTag, SystemTags } from '../db/constants';
import { getSimilarityScaler, getTagSimilarityScaler } from '../db/prefs';

// Isolate state changes and liveQueries to avoid re-rendering of the whole component
const TabsCount = (): ReactElement => {
  const tabvanaWindowId = useLiveQuery(getTabvanaWindowId);
  const windowsCount = useAppSelector((state) => selectWindowsCount(state, tabvanaWindowId));
  const tabsCount = useAppSelector((state) => selectTabsCount(state, tabvanaWindowId));
  return <>{windowsCount} / {tabsCount}</>;
};

const TodoCount = (): ReactElement => <>{useLiveQuery(fetchPendingTodosCount)}</>;
const TagsCount = (): ReactElement => <>{useLiveQuery(fetchTagsCount)}</>;
const StashCount = (): ReactElement => <>{useLiveQuery(fetchStashCount)}</>;
const FlagCount = (): ReactElement => <>{useLiveQuery(fetchFlagCount)}</>;
const UntaggedCount = (): ReactElement => <>{useLiveQuery(fetchUntaggedCount)}</>;
const AllCount = (): ReactElement => <>{useLiveQuery(fetchAllCount)}</>;

const AllTagsPanel = (): ReactElement => {
  const allTags = useLiveQuery(() => fetchTags(SystemTags));

  return <FlexView tags={allTags} />;
};

interface SearchInputProps {
  searchInputRef: React.RefObject<HTMLInputElement>,
};

const SearchInput = ({searchInputRef}: SearchInputProps): ReactElement => {
  const dispatch = useAppDispatch();
  const searchInput = useAppSelector(selectSearchInput);

  return (
    <Input
      style={{ alignSelf: 'center', position: 'relative', left: '-12rem', zIndex: 999 }}
      size="sm"
      slotProps={{ input: { ref: searchInputRef } }}
      name="tabvana-query"
      type="text"
      placeholder="Search"
      onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
        dispatch(setSearchInput(event.target.value))
      }
      value={searchInput}
      onFocus={() => dispatch(setTabIndex(7))}
      onKeyUp={(event) => {
        if (event.key === 'Escape') {
          dispatch(setSearchInput(''));
        }
      }}
    />
  );
};

const Main = (): ReactElement => {
  // const log = useLog('Main');
  // log('call');

  const dispatch = useAppDispatch();
  const tabIndex = useAppSelector(selectTabIndex);

  const searchInputRef = useRef<HTMLInputElement>(null);
  if (tabIndex === SEARCH_TAB_INDEX) {
    searchInputRef.current?.focus();
  }

  useEffect(() => {
    registerTabsListeners(store, { shouldIgnoreUrl: shouldIgnore });
    dispatch(updateWindowsAsync());

    // Listen for re-normalization or other external updates
    const handleMessage = (message: any) => {
        if (message === 'renormalizeDone' || message === 'reloadPrefs') {
            dispatch(updateWindowsAsync());
        }
    };
    chrome.runtime.onMessage.addListener(handleMessage);
    return () => chrome.runtime.onMessage.removeListener(handleMessage);
  }, []); // refresh only on mount
  
  const similarityScaler = useLiveQuery(getSimilarityScaler);
  const tagSimilarityScaler = useLiveQuery(getTagSimilarityScaler);

  useEffect(() => {
    if (similarityScaler !== undefined) {
      document.documentElement.style.setProperty('--similarityScaler', '' + similarityScaler);
    }
  }, [similarityScaler]);

  useEffect(() => {
    if (tagSimilarityScaler !== undefined) {
      document.documentElement.style.setProperty('--tagSimilarityScaler', '' + tagSimilarityScaler);
    }
  }, [tagSimilarityScaler]);

  useEffect(() => {
    const keyDownHandler = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        event.preventDefault();
        dispatch(clearSelection());
      }
    };

    document.addEventListener('keydown', keyDownHandler);

    // 👇️ clean up event listener
    return () => {
      document.removeEventListener('keydown', keyDownHandler);
    };
  }, []);

  return (
    <CssVarsProvider
      defaultMode="dark"
      colorSchemeSelector="#demo_dark-mode-by-default"
      modeStorageKey="demo_dark-mode-by-default"
      disableNestedContext
    >
      <CssBaseline />
      <Sheet className="fill main-window-container">
        <GlobalButtons />
        <Tabs
          size="sm"
          value={tabIndex}
          onChange={(event, index) => {
            dispatch(setTabIndex(index as number));
            if (index === 7) {
              searchInputRef.current?.focus();
            }
          }}
          className="fill flexContainer"
          sx={{ minWidth: 1300 }}
        >
          <TabList className="flexFixedSize" style={{ minHeight: '3rem' }}>
            <Tab color="primary">Todo (<TodoCount />)</Tab>
            <Tab color="primary">
              Tags (<TagsCount />)
            </Tab>
            <Tab color="primary">
              <ListItemDecorator>
                <FontAwesomeIcon icon={faEye} />
              </ListItemDecorator>
              Open (<TabsCount />)
            </Tab>
            <Tab color="primary">
              <ListItemDecorator>
                <FontAwesomeIcon icon={faFlag} />
              </ListItemDecorator>
              Flagged (<FlagCount />)
            </Tab>
            <Tab color="primary">
              <ListItemDecorator>
                <FontAwesomeIcon icon={faCartShopping} />
              </ListItemDecorator>
              Stash (<StashCount />)
            </Tab>
            <Tab color="primary">
              <ListItemDecorator style={{ justifyContent: 'center' }}>
                <FontAwesomeIcon icon={faQuestion} />
              </ListItemDecorator>
              Untagged (<UntaggedCount />)
            </Tab>
            <Tab color="primary">
              <ListItemDecorator style={{ justifyContent: 'center' }}>
                <FontAwesomeIcon icon={faEarth} />
              </ListItemDecorator>
              All (<AllCount />)
            </Tab>
            <Tab color="primary" style={{ width: '13rem' }}></Tab>
            <SearchInput searchInputRef={searchInputRef}/>
          </TabList>

          <TabPanel value={0} className="tabPanel">
            <TodoView />
          </TabPanel>
          <TabPanel value={1} className="tabPanel">
            <AllTagsPanel />
          </TabPanel>
          <TabPanel value={2} className="tabPanel">
            <Windows />
          </TabPanel>
          <TabPanel value={3} className="tabPanel">
            <FlexView singleTag={{ name: FlagTag }} defaultGroupByWindow={true} />
          </TabPanel>
          <TabPanel value={4} className="tabPanel">
            <FlexView singleTag={{ name: StashTag }} defaultGroupByWindow={true} />
          </TabPanel>
          <TabPanel value={5} className="tabPanel">
            <FlexView singleTag={{ name: '#UNTAGGED' }} defaultGroupByWindow={true} />
          </TabPanel>
          <TabPanel value={6} className="tabPanel">
            <FlexView singleTag={{ name: '#ALL' }} defaultGroupByWindow={true} /> 
          </TabPanel>
          <TabPanel value={7} className="tabPanel">
            <SearchResult />
          </TabPanel>
        </Tabs>
      </Sheet>
    </CssVarsProvider>
  );
};

export default Main;
