import type { ReactNode } from 'react'
import type { GameFactoryInput } from 'board-game-engine'
import { Game, useGameserverConnection } from '../src/index'
import ticTacToe from './tic-tac-toe.json'
import { ErrorBoundary } from 'react-error-boundary'
import './styles.css'

const sampleGame = ticTacToe as unknown as GameFactoryInput

export default {
  title: 'Game',
  component: Game,
  className: 'board-game-engine-react',
  args: {
    gameRules: sampleGame,
    numPlayers: 2,
    isSpectator: false,
  },
  argTypes: {
    gameRules: { control: 'object' },
    numPlayers: { control: 'number' },
    isSpectator: { control: 'boolean' },
  },
}

const fallbackRender = ({ error }: { error: Error }) => <div>Invalid Game Rules {error.message}</div>

const Template = ({
  gameRules,
  numPlayers,
  loading,
  isSpectator,
}: {
  gameRules: GameFactoryInput
  numPlayers: number
  loading?: ReactNode
  isSpectator?: boolean
}) => {
  const gameConnection = useGameserverConnection({
    gameRules,
    numPlayers,
  })

  return (
    <div className="story">
      <ErrorBoundary
        resetKeys={[JSON.stringify(gameRules), numPlayers]}
        fallbackRender={fallbackRender}
      >
        <Game
          gameConnection={gameConnection}
          loading={loading}
          isSpectator={isSpectator}
        />
      </ErrorBoundary>
    </div>
  )
}

export const Basic = Template.bind({})

type TemplateProps = Parameters<typeof Template>[0]

export const WithLoading = Object.assign(
  (args: TemplateProps) => (
    <Template
      {...args}
      loading={<div className="story-loading">Loading game…</div>}
    />
  ),
  {
    args: {
      gameRules: sampleGame,
      numPlayers: 2,
    },
  }
)

export const Spectator = Object.assign(Template.bind({}), {
  args: {
    gameRules: sampleGame,
    numPlayers: 2,
    isSpectator: true,
  },
})
