import {useEffect, useState} from "react"
import {
  Box,
  styled,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Typography
} from "@mui/material"
import {CSSTransition, TransitionGroup} from 'react-transition-group'

const StyledTableRow = styled(TableRow)(({ theme, tableType }) => ({
  'tbody &:nth-of-type(odd)': {
    backgroundColor: theme.palette.sncf[tableType].light,
  },
  'th, &:nth-of-type(even)': {
    backgroundColor: theme.palette.sncf[tableType].dark,
  },
  // hide last border
  '&:last-child td, &:last-child th': {
    border: 0,
  },
}));

function TrainsTable({stop, date, time, tableType}) {
  return <>
    <TableContainer>
      <Table>
        <TrainsTableHeader tableType={tableType} />
        <TrainsTableBody stop={stop} date={date} time={time} tableType={tableType} />
      </Table>
    </TableContainer>
  </>
}

function TrainsTableHeader({tableType}) {
  return <>
    <TableHead>
      <StyledTableRow tableType={tableType}>
        <TableCell colSpan="2" fontSize={16} fontWeight="bold">Train</TableCell>
        <TableCell fontSize={16} fontWeight="bold">Heure</TableCell>
        <TableCell fontSize={16} fontWeight="bold">Destination</TableCell>
      </StyledTableRow>
    </TableHead>
  </>
}

function TrainsTableBody({stop, date, time, tableType}) {
  const [trains, setTrains] = useState([])

  useEffect(() => {
    if (stop.id !== undefined) {
      let validTrains = trains.filter(train => {
        if (tableType === "departures")
          return `${train.departure_date}T${train.departure_time_24h}` >= `${date}T${time}`
        else
          return `${train.arrival_date}T${train.arrival_time_24h}` >= `${date}T${time}`
      })
      if (trains.length > 0 && validTrains.length === trains.length)
        return
      console.log(`${trains.length - validTrains.length} trains deleted`)
      fetch(`http://localhost:8000/api/station/next_${tableType}/?stop_id=${stop.id}&date=${date}&time=${time}&offset=${validTrains.length}&limit=${20 - validTrains.length}`)
        .then(response => response.json())
        .then(data => data.results)
        .then(data => {
          setTrains(trains => [...validTrains, ...data])
        })
    }
  }, [stop, tableType, date, time])

  let table_rows = trains.map((train) => <CSSTransition key={train.id} timeout={500} classNames="shrink">
      <TrainRow train={train} tableType={tableType} />
    </CSSTransition>)

  return <>
    <TableBody>
      <TransitionGroup component={null}>
        {table_rows}
      </TransitionGroup>
    </TableBody>
  </>
}

function TrainRow({train, tableType}) {
  const [trip, setTrip] = useState({})
  const [route, setRoute] = useState({})
  const [stopTimes, setStopTimes] = useState([])
  const [trainType, setTrainType] = useState("")

  useEffect(() => {
    if (train.trip !== undefined) {
      fetch(`http://localhost:8000/api/gtfs/trip/${train.trip}/`)
        .then(response => response.json())
        .then(t => {
          t.stop_times = []
          setTrip(t)
        })
    }
  }, [train.trip])

  useEffect(() => {
    if (trip.route !== undefined) {
      fetch(`http://localhost:8000/api/gtfs/route/${trip.route}/`)
        .then(response => response.json())
        .then(data => {
          setRoute(data)
        })
    }
  }, [trip.route])

  useEffect(() => {
    if (route !== undefined) {
      setTrainType(getTrainType(train, route))
    }
  }, [train, route]);

  useEffect(() => {
    if (trip.route !== undefined) {
      fetch(`http://localhost:8000/api/gtfs/stop_time/?trip=${trip.id}&order=stop_sequence&limit=1000`)
        .then(response => response.json())
        .then(data => data.results)
        .then(stop_times => {
          Promise.all(stop_times.map(stop_time =>
            fetch(`http://localhost:8000/api/gtfs/stop/${stop_time.stop}/`).then(response => response.json())
          )).then(stops => {
            setStopTimes(stop_times.map((stop_time, index) => {
              stop_time.stop = stops[index]
              return stop_time
            }))
          })
        })
    }
  }, [trip.route])

  let headline = stopTimes[tableType === "departures" ? stopTimes.length - 1 : 0]?.stop ?? {name: "Chargement…"}

  let stops_filter
  if (tableType === "departures")
    stops_filter = (stop_time) => stop_time.stop_sequence > train.stop_sequence && stop_time.drop_off_type === 0
  else
    stops_filter = (stop_time) => stop_time.stop_sequence < train.stop_sequence && stop_time.pickup_type === 0
  let stops_names = stopTimes.filter(stops_filter).map(stop_time => stop_time?.stop.name ?? "").join(", ")

  return <>
    <StyledTableRow tableType={tableType}>
      <TableCell>
        <div>
          <Box display="flex"
               justifyContent="center"
               alignItems="center"
               textAlign="center"
               width="4em"
               height="4em"
               borderRadius="15%"
               fontWeight="bold"
               backgroundColor={`#${getBackgroundColor(train, route)}`}
               color={`#${getTextColor(train, route)}`}>
            {trainType}
          </Box>
        </div>
      </TableCell>
      <TableCell>
        <Box display="flex" alignItems="center" justifyContent="center" textAlign="center">
          <div>
            <div>{trip.short_name}</div>
            <div>{trip.headsign}</div>
          </div>
        </Box>
      </TableCell>
      <TableCell>
        <Box display="flex" alignItems="center" justifyContent="center" fontWeight="bold" color="#FFED02" fontSize={24}>
          {getDisplayTime(train, tableType)}
        </Box>
      </TableCell>
      <TableCell>
        <Typography fontSize={24} fontWeight="bold">{headline.name}</Typography>
        <span className="stops">{stops_names}</span>
      </TableCell>
    </StyledTableRow>
  </>
}

function getTrainType(train, route) {
  if (train.id.startsWith("IDFM"))
    return route.short_name
  else {
    let trainType = train.stop.split("StopPoint:OCE")[1].split("-")[0]
    if (trainType === "Train TER")
      trainType = "TER"
    else if (trainType === "INTERCITES")
      trainType = "INTER-CITÉS"
    else if (trainType === "INTERCITES de nuit")
      trainType = "INTER-CITÉS de nuit"
    return trainType
  }
}

function getBackgroundColor(train, route) {
  if (route.color)
    return route.color
  else if (getTrainType(train, route) === "OUIGO")
    return "E60075"
  return "FFFFFF"
}

function getTextColor(train, route) {
  if (route.text_color)
    return route.text_color
  else {
    let trainType = getTrainType(train, route)
    switch (trainType) {
      case "OUIGO":
        return "FFFFFF"
      case "TGV INOUI":
        return "9B2743"
      case "ICE":
        return "B4B4B4"
      case "INTER-CITÉS":
      case "INTER-CITÉS de nuit":
        return "404042"
      default:
        return "000000"
    }
  }
}

function getDisplayTime(train, tableType) {
  let time = tableType === "departures" ? train.departure_time : train.arrival_time
  let day_split = time.split(' ')
  return day_split[day_split.length - 1].substring(0, 5)
}

export default TrainsTable;