import React from 'react'

import Alert from '@mui/material/Alert/index.js'
import Divider from '@mui/material/Divider/index.js'
import Card from '@mui/material/Card/index.js'
import CardContent from '@mui/material/CardContent/index.js'
import sortBy from 'lodash.sortby'

import { Markdown } from '../Markdown/index.js'

import BailOutErrorBoundary from '../BailOutErrorBoundary/index.js'

import { levelAchieved } from '../../utils/levelAchieved.js'
import { getPlayerName } from '../../utils/getPlayerName.js'
import FarmhandContext from '../Farmhand/Farmhand.context.js'

import CowCard from '../CowCard/index.js'

import OnlinePeer from './OnlinePeer/index.js'

const OnlinePeersView = ({
  activePlayers,
  cowIdOfferedForTrade,
  cowInventory,
  playerId,
  latestPeerMessages,
  peers,
}: {
  activePlayers: number
  cowIdOfferedForTrade: string
  cowInventory: farmhand.cow[]
  playerId: string
  latestPeerMessages: { playerId: string; message: string; severity?: string }[]
  peers: Record<string, any>
}) => {
  const peerKeys = Object.keys(peers)

  const cowOfferedForTrade = cowInventory.find(
    ({ id }: farmhand.cow) => id === cowIdOfferedForTrade
  )

  // Filter out peers that may have connected but not sent data yet.
  const populatedPeers = peerKeys.filter(peerId => peers[peerId])

  return (
    <div {...{ className: 'OnlinePeersView' }}>
      {activePlayers - 1 > populatedPeers.length && (
        <p>Getting player information...</p>
      )}
      <h3>Your player name</h3>
      <Card>
        <CardContent>
          <strong>{getPlayerName(playerId)}</strong>
        </CardContent>
      </Card>
      {cowOfferedForTrade && (
        <>
          <Divider />
          <h3>You are offering to trade away</h3>
          <CowCard
            {...{
              cow: cowOfferedForTrade,
              isCowOfferedForTradeByPeer: false,
              isSelected: false,
            }}
          />
        </>
      )}
      {populatedPeers.length > 0 && (
        <>
          <Divider />
          <ul className="card-list">
            {sortBy(populatedPeers, [
              peerId =>
                // Use negative value to reverse sort order
                -levelAchieved(peers[peerId].experience || 0),
            ]).map(peerId => (
              <BailOutErrorBoundary key={peerId}>
                <OnlinePeer {...{ peer: peers[peerId] }} />
              </BailOutErrorBoundary>
            ))}
          </ul>
        </>
      )}
      {latestPeerMessages.length > 0 && (
        <>
          <Divider />
          <ul>
            {latestPeerMessages.map(
              (
                {
                  playerId: peerPlayerId,
                  message,
                  severity = 'info',
                }: { playerId: string; message: string; severity?: string },
                messageIndex: number
              ) => (
                <li key={messageIndex}>
                  <Alert
                    {...{
                      elevation: 3,
                      severity: severity as any,
                    }}
                  >
                    <Markdown
                      {...{
                        children: `**${getPlayerName(
                          peerPlayerId
                        )}** ${message}`,
                      }}
                    />
                  </Alert>
                </li>
              )
            )}
          </ul>
        </>
      )}
    </div>
  )
}

export { OnlinePeersView }

export default function Consumer(
  props: Partial<Parameters<typeof OnlinePeersView>[0]>
) {
  return (
    <FarmhandContext.Consumer>
      {({ gameState, handlers }) => (
        <OnlinePeersView
          {...({
            ...gameState,
            ...handlers,
            ...props,
          } as Parameters<typeof OnlinePeersView>[0])}
        />
      )}
    </FarmhandContext.Consumer>
  )
}
