import * as React from 'react';
import { View, Text, useWindowDimensions, Alert, Pressable } from 'react-native';
import { useTranslation } from 'react-i18next';
import { GameScreenProps } from '../types';
import { useState } from 'react';
import { Game, GameUsersConnectionInfo, GameMove, LoadingState, BoardViewModel, PitAnimator, getColorByBrightness } from "@mancala/core";
import { MancalaGame, Pit } from 'mancala.js';
import { v4 } from 'uuid';
import { channel_on_game_update, channel_on_game_crashed, channel_on_game_user_leave, channel_on_user_connection_change, channel_listen_game_events, channel_unlisten_game_events, channel_leave_game, channel_game_move } from '@mancala/core';
import Util from '../util/Util';
import Snackbar from 'react-native-snackbar';
import PageContainer from '../components/PageContainer';
import Center from '../components/Center';
import InfoPanel from '../components/InfoPanel';
import LoadingComponent from '../components/LoadingComponent';
import UserStatus from '../components/UserStatus';
import BoardToolbar from '../components/board/BoardToolbar';
import BoardView from '../components/board/BoardView';
import CircularPanel from '../components/CircularPanel';
import { SvgXml } from 'react-native-svg';
import helpSvg from '../svg/help';
export function GameScreen({ navigation, route }: GameScreenProps) {

  const { context, gameId, userKey } = route.params;
  const { t } = useTranslation();

  const [game, setGame] = useState<Game | undefined>(undefined);

  const [userKeyWhoLeave, setUserKeyWhoLeave] = useState<string | undefined>(undefined);

  const [boardViewModel, setBoardViewModel] = useState<BoardViewModel | undefined>(undefined);

  const [boardId, setBoardId] = useState<string>("-1");

  const [pitAnimator, setPitAnimator] = useState<PitAnimator | undefined>(undefined);

  // It is a flag for ongoing action such as send game move.
  // We have to block future actions if there is an ongoing action.
  const [hasOngoingAction, setHasOngoingAction] = useState<boolean>(false);

  const [gameUsersConnectionInfo, setGameUsersConnectionInfo] = useState<GameUsersConnectionInfo | undefined>();

  const { height, width } = useWindowDimensions();

  const [gameLoadingState, setLoadingStateGame] = useState<LoadingState<Game>>(LoadingState.Unset());

  const checkIsSpectator = (game: Game) => userKey !== game.mancalaGame.player1Id && userKey !== game.mancalaGame.player2Id;

  const mancalaGame: MancalaGame | undefined = game?.mancalaGame;
  const isSpectator = game ? checkIsSpectator(game) : undefined;
  const isPlayer2 = !isSpectator && userKey === mancalaGame?.player2Id;

  const onGameUpdate = (pitAnimator: PitAnimator, newGame: Game) => {
    setGame(newGame);
    pitAnimator.setUpdatedGame(newGame);
    setHasOngoingAction(false);
    setGameUsersConnectionInfo(newGame.gameUsersConnectionInfo);
  }

  const isUserOnline = (userId: string) => {
    if (!gameUsersConnectionInfo) return false;
    const user1ConnectionInfo = gameUsersConnectionInfo.user1ConnectionInfo;
    const user2ConnectionInfo = gameUsersConnectionInfo.user2ConnectionInfo;
    if (user1ConnectionInfo.userId === userId) return user1ConnectionInfo.isOnline;
    if (user2ConnectionInfo.userId === userId) return user2ConnectionInfo.isOnline;
    return false;
  }

  const onGameUpdateEvent = (pitAnimator: PitAnimator, message: Object) => {
    const newGame: Game = message as Game;
    newGame.mancalaGame = MancalaGame.createFromMancalaGame(newGame.mancalaGame);
    onGameUpdate(pitAnimator, newGame);
  }
  const onGameCrashed = (message: any) => {
    const newCrashMessage = message as string;
    Snackbar.show({ text: t("InternalErrorOccurred") });
    console.error("on_game_crash");
    console.error(newCrashMessage);
  }
  const onGameUserLeave = (message: any) => {
    const userKeyWhoLeave = message;
    setUserKeyWhoLeave(userKeyWhoLeave);
    setHasOngoingAction(false);
  };
  const onUserConnectionChange = (message: any) => {
    const gameUsersConnectionInfo = message as GameUsersConnectionInfo;
    setGameUsersConnectionInfo(gameUsersConnectionInfo);
  };

  const listenMessages = (game: Game, pitAnimator: PitAnimator): () => void => {
    const _onGameUpdate = (message: object) => onGameUpdateEvent(pitAnimator, message);
    context.rtmt.addMessageListener(channel_on_game_update, _onGameUpdate);
    context.rtmt.addMessageListener(channel_on_game_crashed, onGameCrashed);
    context.rtmt.addMessageListener(channel_on_game_user_leave, onGameUserLeave);
    context.rtmt.addMessageListener(channel_on_user_connection_change, onUserConnectionChange);
    checkIsSpectator(game) && userKey && context.rtmt.sendMessage(channel_listen_game_events, game.id);
    return () => {
      checkIsSpectator(game) && userKey && context.rtmt.sendMessage(channel_unlisten_game_events, game.id);
      context.rtmt.removeMessageListener(channel_on_game_update, _onGameUpdate);
      context.rtmt.removeMessageListener(channel_on_game_crashed, onGameCrashed);
      context.rtmt.removeMessageListener(channel_on_game_user_leave, onGameUserLeave);
      context.rtmt.removeMessageListener(channel_on_user_connection_change, onUserConnectionChange);
    }
  };

  const updateBoardViewModel = (boardViewModel: BoardViewModel) => {
    boardViewModel.id = v4();
    setBoardId(boardViewModel.id);
    setBoardViewModel(boardViewModel);
  };

  const getBoardIndex = (index: number) => {
    if (!game || !mancalaGame) return -1;
    const pitsLenght = mancalaGame.board.pits.length;
    if (userKey === mancalaGame.player2Id) return index + pitsLenght / 2;
    return index;
  };

  const getOpponentId = () => mancalaGame?.player1Id === userKey ? mancalaGame?.player2Id : mancalaGame?.player1Id;

  const checkHasAnOngoingAction = () => hasOngoingAction;

  const onLeaveGameClick = () => {
    if (Util.checkConnectionAndMaybeAlert(context, t("ConnectionLost"))) return;
    Alert.alert(t('AreYouSureToLeaveGame'), "", [
      {
        text: t('Cancel'),
        style: 'cancel',
      },
      {
        text: t('Yes'),
        onPress: () => {
          context.rtmt.sendMessage(channel_leave_game, {});
          updateHeaderButton();
        },
        style: 'default',
      },
    ],
      {
        cancelable: true,
        onDismiss: () => { }
      });
  };

  const onNewGameClick = () => {
    if (Util.checkConnectionAndMaybeAlert(context, t("ConnectionLost"))) return;
    navigation.replace("Loby", { context })
  };

  const onPitSelect = (index: number, pit: Pit) => {
    if (!game || isSpectator || !userKey) {
      return;
    }
    if (userKeyWhoLeave) {
      Snackbar.show({ text: t("GameEnded") });
      return;
    }
    if (game.mancalaGame.state === "ended") {
      Snackbar.show({ text: t("GameEnded") });
      return;
    }
    if (Util.checkConnectionAndMaybeAlert(context, t("ConnectionLost"))) return;
    if (game.mancalaGame.getPlayerIdByIndex(index) !== userKey) {
      Snackbar.show({ text: t("UCanOnlyPlayYourOwnPits") });
      return;
    }
    const pitIndexForUser = index % (game.mancalaGame.board.totalPitCount() / 2);
    if (!game.mancalaGame.canPlayerMove(userKey, pitIndexForUser)) {
      Snackbar.show({ text: t("OpponentTurn") });
      return;
    }
    if (checkHasAnOngoingAction()) {
      Snackbar.show({ text: t("UMustWaitUntilCurrentMoveComplete") });
      return;
    }
    if (!boardViewModel) return;
    //TODO: this check should be in mancala.js
    if (pit.stoneCount === 0) {
      Snackbar.show({ text: t("UCanNotPlayEmptyPit") });
      return;
    }
    setHasOngoingAction(true);
    boardViewModel.pits[getBoardIndex(pitIndexForUser)].pitColor =
      context.themeManager.theme.pitSelectedColor;
    updateBoardViewModel(boardViewModel);
    const gameMove: GameMove = { index: pitIndexForUser };
    context.rtmt.sendMessage(channel_game_move, gameMove);
  };

  React.useEffect(() => {
    let pitAnimator: PitAnimator | undefined;
    let unlistenMessages: () => void;
    setLoadingStateGame(LoadingState.Loading())
    context.gameStore.get(gameId!!).then((game) => {
      if (game) {
        pitAnimator = new PitAnimator(context.themeManager, updateBoardViewModel);
        setPitAnimator(pitAnimator);
        onGameUpdate(pitAnimator, game);
        unlistenMessages = listenMessages(game, pitAnimator);
        setLoadingStateGame(LoadingState.Loaded({ value: game }))
      } else {
        setLoadingStateGame(LoadingState.Error({ errorMessage: t('GameNotFound') }))
      }
    })
    return () => {
      unlistenMessages?.();
      pitAnimator?.dispose();
    };
  }, []);

  const updateHeaderButton = () => {
    const isGameEnded = game?.mancalaGame.state === "ended" || leftPlayer;
    navigation.setOptions({
      headerRight: () => (
        <View style={{
          display: "flex",
          flexDirection: "row",
          alignItems: "center",
          gap: 5
        }}>
          <Pressable onPress={() => {
            if (isGameEnded) {
              onNewGameClick();
            } else {
              onLeaveGameClick();
            }
          }}>
            <CircularPanel color={context.themeManager.theme?.background} children={<Text style={{ color: context.themeManager.theme.textColor }}>{isGameEnded ? t('NewGame') : t('Leave')}</Text>} />
          </Pressable>
          <Pressable onPress={() => {
            navigation.push("Help", { context })
          }}>
            <SvgXml xml={helpSvg.replaceAll("customColor", textColorOnAppBar)} width="24" height="24" />
          </Pressable>
        </View>

      ),
    });
  }

  React.useEffect(() => {
    updateHeaderButton();
  }, [navigation, game, userKeyWhoLeave]);

  const textColorOnAppBar = getColorByBrightness(
    context.themeManager.theme.appBarBgColor,
    context.themeManager.theme.textColor,
    context.themeManager.theme.textLightColor
  );
  const isMobile = width < 600;

  const renderNewGameBtn = isSpectator || (userKeyWhoLeave || !game || (game && game.mancalaGame.state == "ended"));
  const showBoardView = game && boardViewModel && userKey && true;
  const topLocatedUserId = (isSpectator ? mancalaGame?.player2Id : getOpponentId()) || "0";
  const bottomLocatedUserId = (isSpectator ? mancalaGame?.player1Id : userKey) || "1";
  const topLocatedUser = {
    id: topLocatedUserId,
    name: "Anonymous",
    isOnline: isUserOnline(topLocatedUserId),
    isAnonymous: true
  };
  const bottomLocatedUser = {
    id: bottomLocatedUserId,
    name: "Anonymous",
    isOnline: isSpectator ? isUserOnline(bottomLocatedUserId) : context.rtmt.connectionState === "connected",
    isAnonymous: true
  };
  const currentUser = isSpectator ? {
    id: "2",
    name: "Anonymous",
    isOnline: context.rtmt.connectionState === "connected",
    isAnonymous: true
  } : bottomLocatedUser;
  const leftPlayer = userKeyWhoLeave ? (userKeyWhoLeave === topLocatedUser.id ? topLocatedUser : bottomLocatedUser) : undefined;
  return (
    <PageContainer context={context}>
      {/* {renderHeaderBar()} */}
      {renderMobileBoardToolbar()}
      {buildBoardTopToolbar()}
      {showBoardView && (
        <BoardView
          game={game}
          boardId={boardId}
          boardViewModel={boardViewModel}
          context={context}
          onPitSelect={onPitSelect}
          revert={isPlayer2} />
      )}
      <Center>
        <LoadingComponent context={context} loadingState={gameLoadingState}></LoadingComponent>
      </Center>
    </PageContainer>
  );

  //function renderHeaderBar() {
  //  return <HeaderBar color={theme?.appBarBgColor}>
  //    <Row>
  //      <Link style={{ textDecoration: 'none' }} to={"/"}>
  //        <HeaderbarIcon />
  //      </Link>
  //      <Link style={{ textDecoration: 'none' }} to={"/"}>
  //        <HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
  //      </Link>
  //    </Row>
  //    <Row>
  //      <ThemeSwitchMenu context={context} textColor={textColorOnAppBar} />
  //      <Button
  //        context={context}
  //        color={context.themeManager.theme.pitColor}
  //        text={renderNewGameBtn ? context.texts.NewGame : context.texts.Leave}
  //        onClick={renderNewGameBtn ? onNewGameClick : onLeaveGameClick} />
  //    </Row>
  //  </HeaderBar>;
  //}

  function renderMobileBoardToolbar() {
    return <BoardToolbar style={{ justifyContent: "center" }} visible={showBoardView && isMobile || false}>
      <View />
      {buildInfoPanel({ visible: isMobile })}
      <View />
    </BoardToolbar>;
  }

  function buildBoardTopToolbar() {
    return <BoardToolbar style={{ alignItems: "flex-end" }} visible={showBoardView || false}>
      <UserStatus style={{ marginLeft: 10, width: 100 }} context={context}
        layoutMode="left" user={topLocatedUser} visible={showBoardView || false} />
      {buildInfoPanel({ visible: !isMobile })}
      <UserStatus style={{ marginLeft: 10, width: 100 }} context={context} layoutMode="right" user={bottomLocatedUser} visible={showBoardView || false} />
    </BoardToolbar>;
  }

  function buildInfoPanel(params: { visible: boolean }) {
    return (
      <InfoPanel
        style={{ marginTop: 10, marginBottom: 10 }}
        context={context}
        game={game}
        currentUser={currentUser}
        whitePlayer={topLocatedUser}
        blackPlayer={bottomLocatedUser}
        leftPlayer={leftPlayer}
        visible={params.visible}
        isSpectator={isSpectator} />
    );
  }
}
