import { useNavigate, Routes, Route } from 'react-router-dom';
import PropTypes from 'prop-types';

import { useClientIdentity } from './client.js';

import { Page } from './page.js';
import { Heading } from './widgets/heading.js';
import { ButtonBar, Button } from './widgets/buttonBar.js';

import { Tutorial } from './features/tutorial/tutorial.js';
import { RULES_TUTORIAL } from './tutorials/rules.js';
import { NotificationHandler } from './features/lobby/notificationHandler.js';
import { Account } from './features/lobby/account.js';
import { Invitation } from './features/lobby/invitation.js';
import { GameMenu } from './features/lobby/gameMenu.js';
import { SettingsMenu } from './features/lobby/settingsMenu.js';
import { Player } from './features/play/player.js';
import { Editor } from './features/play/editor.js';
import { AbruptShutdownRecovery } from './features/play/abruptShutdownRecovery.js';
import { Network } from './features/play/network.js';
import { OneGameMonitor } from './features/play/monitor.js';

import './app.css';
import homeIcon from './icons/home.svg';
import rulesIcon from './icons/rules.svg';
import localIcon from './icons/local.svg';
import editIcon from './icons/edit.svg';
import analysisIcon from './icons/analysis.svg';
import remoteIcon from './icons/remote.svg';

import GAME_LIBRARY from './gameLibrary.js';

const GAME = GAME_LIBRARY.get('boost-9-9-2-8-2');
const DRAGON_COUNT = 7;
const ANALYSIS_DEPTH = 5;

function PageWithNavigationBar(props) {
  const {
    homeAltText,
    homeTo,
    rulesAltText,
    rulesTo,
    localAltText,
    localTo,
    editAltText,
    editTo,
    analysisAltText,
    analysisTo,
    remoteAltText,
    remoteTo,
  } = {
    homeAltText: 'Home',
    homeTo: '/',
    rulesAltText: 'Learn the Rules',
    rulesTo: '/rules',
    localAltText: 'Play a Game on this Device',
    localTo: '/local/gameMenu',
    editAltText: 'Edit a Position',
    editTo: '/edit/gameMenu',
    analysisAltText: 'Analyze a Game',
    analysisTo: '/analysis/gameMenu',
    remoteAltText: 'Play a Network Game',
    remoteTo: '/remote/gameMenu',
    ...props,
  };

  const navigate = useNavigate();

  return (
    <Page>
      <ButtonBar>
        <Button
          image={homeIcon}
          altText={homeAltText}
          disabled={homeTo === undefined}
          onClick={homeTo !== undefined ? () => navigate(homeTo) : undefined} />
        <Button
          image={rulesIcon}
          altText={rulesAltText}
          disabled={rulesTo === undefined}
          onClick={rulesTo !== undefined ? () => navigate(rulesTo) : undefined} />
        <Button
          image={localIcon}
          altText={localAltText}
          disabled={localTo === undefined}
          onClick={localTo !== undefined ? () => navigate(localTo) : undefined} />
        <Button
          image={editIcon}
          altText={editAltText}
          disabled={editTo === undefined}
          onClick={editTo !== undefined ? () => navigate(editTo) : undefined} />
        <Button
          image={analysisIcon}
          altText={analysisAltText}
          disabled={analysisTo === undefined}
          onClick={analysisTo !== undefined ? () => navigate(analysisTo) : undefined} />
        <Button
          image={remoteIcon}
          altText={remoteAltText}
          disabled={remoteTo === undefined}
          onClick={remoteTo !== undefined ? () => navigate(remoteTo) : undefined} />
      </ButtonBar>
      {props.children}
    </Page>
  );
}

PageWithNavigationBar.propTypes = {
  homeAltText: PropTypes.string,
  homeTo: PropTypes.string,
  rulesAltText: PropTypes.string,
  rulesTo: PropTypes.string,
  localAltText: PropTypes.string,
  localTo: PropTypes.string,
  editAltText: PropTypes.string,
  editTo: PropTypes.string,
  analysisAltText: PropTypes.string,
  analysisTo: PropTypes.string,
  remoteAltText: PropTypes.string,
  remoteTo: PropTypes.string,
};

export function App() {
  const clientIdentity = useClientIdentity();
  const invitationTarget = clientIdentity !== undefined ? '/remote/invitation' : '/remote/invitationLogin';

  const navigate = useNavigate();

  const home =
    <PageWithNavigationBar homeTo={undefined}>
      <nav>
        <Heading text={'Boost Board Game'} />
        <ButtonBar>
          <Button text={'Learn the Rules'} autofocus={true} onClick={() => navigate('/rules')} />
        </ButtonBar>
        <ButtonBar>
          <Button text={'Play a Game on this Device'} onClick={() => navigate('/local/gameMenu')} />
        </ButtonBar>
        <ButtonBar>
          <Button text={'Play a Network Game'} onClick={() => navigate('/remote/gameMenu')} />
        </ButtonBar>
        <ButtonBar>
          <Button text={'Accept a Game Invitation'} onClick={() => navigate(invitationTarget)} />
        </ButtonBar>
        <div />
      </nav>
    </PageWithNavigationBar>;

  const rulesTutorial =
    <PageWithNavigationBar rulesTo={undefined}>
      <Heading text={RULES_TUTORIAL.title} />
      <Tutorial slot={'rules'} tutorial={RULES_TUTORIAL} />
    </PageWithNavigationBar>;

  const localGameMenu =
    <PageWithNavigationBar localTo={undefined}>
      <GameMenu
        slot={'local'}
        gameIdentifier={GAME.identifier}
        dragons={DRAGON_COUNT}
        remote={false}
        newGameTo={'/local/settingsMenu'}
        loadGameTo={'/local'} />
    </PageWithNavigationBar>;
  const localSettingsMenu =
    <PageWithNavigationBar>
      <Heading text={'Choose Settings'} />
      <SettingsMenu slot={'local'} remote={false} backTo={'/local/gameMenu'} to={'/local'} />
    </PageWithNavigationBar>;
  const localBoard =
    <PageWithNavigationBar
      localAltText={'Play another Game on this Device'}
      editAltText={'Edit this Position'}
      editTo={'/edit'}
      analysisAltText={'Analyze from this Position'}
      analysisTo={'/analysis'}>
      <Heading text={'Local Game'} />
      <Player
        slot={'local'}
        remote={false}
        analysisOnly={false}
        analysisDepth={ANALYSIS_DEPTH}
        settingsTo={'/local/settingsMenu'} />
    </PageWithNavigationBar>;

  const editGameMenu =
    <PageWithNavigationBar editTo={undefined}>
      <GameMenu
        slot={'local'}
        gameIdentifier={GAME.identifier}
        dragons={DRAGON_COUNT}
        remote={false}
        newGameTo={'/edit'}
        loadGameTo={'/edit'} />
    </PageWithNavigationBar>;
  const editBoard =
    <PageWithNavigationBar
      localAltText={'Play from this Position'}
      localTo={'/local'}
      editAltText={'Edit another Position'}
      analysisAltText={'Analyze from this Position'}
      analysisTo={'/analysis'}>
      <Heading text={'Editor'} />
      <Editor slot={'local'} />
    </PageWithNavigationBar>;

  const analyzeGameMenu =
    <PageWithNavigationBar analysisTo={undefined}>
      <GameMenu
        slot={'local'}
        gameIdentifier={GAME.identifier}
        dragons={DRAGON_COUNT}
        remote={false}
        newGameTo={'/analysis'}
        loadGameTo={'/analysis'} />
    </PageWithNavigationBar>;
  const analyzeBoard =
    <PageWithNavigationBar
      localAltText={'Play from this Position'}
      localTo={'/local'}
      editAltText={'Edit this Position'}
      editTo={'/edit'}
      analysisAltText={'Analyze another Game'}>
      <Heading text={'Analysis'} />
      <Player slot={'local'} remote={false} analysisOnly={true} analysisDepth={ANALYSIS_DEPTH} />
    </PageWithNavigationBar>;

  const accountPage =
    <PageWithNavigationBar>
      <Heading text={'Account'} />
      <Account listTo={'/remote/gameMenu'} />
    </PageWithNavigationBar>;
  const remoteGameMenu =
    <PageWithNavigationBar remoteTo={undefined}>
      <GameMenu
        slot={'remote'}
        gameIdentifier={GAME.identifier}
        dragons={DRAGON_COUNT}
        remote={true}
        accountTo={'/remote/account'}
        acceptTo={'/remote/invitation'}
        newGameTo={'/remote/settingsMenu'}
        loadGameTo={'/remote'} />
    </PageWithNavigationBar>;
  const invitationLoginPage =
    <PageWithNavigationBar>
      <Heading text={'Account'} />
      <Account listTo={'/remote/invitation'} />
    </PageWithNavigationBar>;
  const invitationAcceptancePage =
    <PageWithNavigationBar>
      <Heading text={'Accept Invitation'} />
      <Invitation slot={'remote'} to={'/remote'} backTo={'/remote/gameMenu'} />
    </PageWithNavigationBar>;
  const remoteSettingsMenu =
    <PageWithNavigationBar>
      <Heading text={'Choose Settings'} />
      <SettingsMenu slot={'remote'} remote={true} backTo={'/remote/gameMenu'} to={'/remote'} />
    </PageWithNavigationBar>;
  const remoteBoard =
    <PageWithNavigationBar>
      <Heading text={'Network Game'} />
      <Player
        slot={'remote'}
        remote={true}
        analysisOnly={false}
        analysisDepth={ANALYSIS_DEPTH}
        backTo={'/remote/gameMenu'} />
      <OneGameMonitor slot={'remote'} />
    </PageWithNavigationBar>;

  const notification =
    <PageWithNavigationBar>
      <NotificationHandler slot={'remote'} backTo={'/'} accountTo={'/notificationLogin'} to={'/remote'} />
    </PageWithNavigationBar>;
  const notificationLoginPage =
    <PageWithNavigationBar>
      <Heading text={'Account'} />
      <Account listTo={'/remote'} />
    </PageWithNavigationBar>;

  return (
    <>
      <Routes>
        <Route path={'/'} element={home} />
        <Route path={'/rules/*'} element={rulesTutorial} />
        <Route path={'/local/gameMenu/*'} element={localGameMenu} />
        <Route path={'/local/settingsMenu/*'} element={localSettingsMenu} />
        <Route path={'/local/*'} element={localBoard} />
        <Route path={'/edit/gameMenu/*'} element={editGameMenu} />
        <Route path={'/edit/*'} element={editBoard} />
        <Route path={'/analysis/gameMenu/*'} element={analyzeGameMenu} />
        <Route path={'/analysis/*'} element={analyzeBoard} />
        <Route path={'/remote/account/*'} element={accountPage} />
        <Route path={'/remote/gameMenu/*'} element={remoteGameMenu} />
        <Route path={'/remote/invitationLogin/*'} element={invitationLoginPage} />
        <Route path={'/remote/invitation/*'} element={invitationAcceptancePage} />
        <Route path={'/remote/settingsMenu/*'} element={remoteSettingsMenu} />
        <Route path={'/remote/*'} element={remoteBoard} />
        <Route path={'/notification/*'} element={notification} />
        <Route path={'/notificationLogin/*'} element={notificationLoginPage} />
      </Routes>
      <AbruptShutdownRecovery />
      <Network slot={'remote'} />
    </>
  );
}

if (navigator.serviceWorker) {
  console.log('Listening to service worker messages…');
  navigator.serviceWorker.addEventListener('message', (message) => {
    if (typeof message.data.hash === 'string') {
      globalThis.location.hash = message.data.hash;
    }
  });
}