import React, { useState, useEffect } from 'react'

import Header from '../components/header'
import LoadingIndicator from '../components/LoadingIndicator'

import styles from './ranklist.module.css'
import constants from '../constants.json'

const selectOptions = {
  newQuestions: { name: 'Beküldött új kérdések' },
  allQuestions: { name: 'Megoldott kérdések' },
  count: { name: 'Megoldott tesztek' },
}

const sinceOptions = {
  all: {
    name: 'All time',
  },
  monthly: { name: 'Havi' },
  weekly: { name: 'Heti' },
  daily: { name: 'Napi' },
}

function getTimeString(date) {
  return (
    date.getFullYear() +
    '-' +
    ('0' + (date.getMonth() + 1)).slice(-2) +
    '-' +
    ('0' + date.getDate()).slice(-2)
  )
}

function getSinceDate(keyword) {
  if (keyword === 'all') {
    return null
  }

  const date = new Date()
  if (keyword === 'daily') {
    date.setDate(date.getDate() - 1)
  } else if (keyword === 'weekly') {
    date.setDate(date.getDate() - 7)
  } else if (keyword === 'monthly') {
    date.setDate(date.getDate() - 30)
  }
  return date
}

async function getListFromServer(since) {
  return new Promise((resolve, reject) => {
    let query = ''
    if (since && since !== 'all') {
      query = `?since=${getTimeString(getSinceDate(since))}`
    }
    fetch(`${constants.apiUrl}ranklist${query}`, {
      credentials: 'include',
      Accept: 'application/json',
      'Content-Type': 'application/json',
    })
      .then((resp) => {
        return resp.json()
      })
      .then((data) => {
        resolve(data)
      })
      .catch((error) => {
        reject(error)
      })
  })
}

function sortDataBy(data, key) {
  return data.sort((a, b) => {
    if (a[key] < b[key]) {
      return 1
    } else if (a[key] > b[key]) {
      return -1
    } else {
      return 0
    }
  })
}

export default function RankList({ globalData, globalState, setGlobalState }) {
  const userId = globalData.userId
  const [ranklist, setRanklist] = useState(null)
  const [selfUserId, setSelfUserId] = useState('...')
  const [key, setKey] = useState('newQuestions')
  const [since, setSince] = useState('all')
  const [sum, setSum] = useState()
  const [ownEntryOnTop, setOwnEntryOnTop] = useState(false)

  const getList = () => {
    setSum()
    setRanklist(null)
    if (globalState[`rankilst_${since}`]) {
      const { list, sum, selfuserId } = globalState[`rankilst_${since}`]
      setRanklist(list || [])
      setSum(sum)
      if (selfuserId) {
        setSelfUserId(selfuserId)
      }
    } else {
      getListFromServer(since)
        .then((data) => {
          const { list, sum, selfuserId } = data
          setRanklist(list || [])
          setSum(sum)
          if (selfuserId) {
            setSelfUserId(selfuserId)
          }
          setGlobalState({
            [`rankilst_${since}`]: data,
          })
        })
        .catch(() => {
          setRanklist(null)
        })
    }
  }

  useEffect(() => {
    getList()
  }, [])

  useEffect(() => {
    getList()
  }, [since])

  const list =
    ranklist &&
    sortDataBy(ranklist, key).reduce((acc, entry, i) => {
      if (entry.userId === userId && ownEntryOnTop) {
        return [{ rank: i, ...entry }, ...acc]
      } else {
        return [...acc, { rank: i, ...entry }]
      }
    }, [])

  const updateSince = (keyword) => {
    setSince(keyword)
  }

  return (
    <div>
      <Header title={'Ranklista'} />
      <div className={styles.container}>
        <div>
          <center>
            <div className={'pageHeader'}>
              <h1>Ranklista</h1>
            </div>
          </center>
          <div
            className={styles.infoText}
          >{`A felhasználó ID-d: #${selfUserId}`}</div>
          <div className={'selectContainer'}>
            <div>Megjelenítés: </div>
            <select
              onChange={(e) => {
                updateSince(e.target.value)
              }}
            >
              {Object.keys(sinceOptions).map((key) => {
                const val = sinceOptions[key]
                return (
                  <option key={key} value={key}>
                    {val.name}
                  </option>
                )
              })}
            </select>
          </div>
          <div className={'selectContainer'}>
            <div>Rendezés: </div>
            <select
              value={key}
              onChange={(e) => {
                setKey(e.target.value)
              }}
            >
              {Object.keys(selectOptions).map((key) => {
                const val = selectOptions[key]
                return (
                  <option key={key} value={key}>
                    {val.name}
                  </option>
                )
              })}
            </select>
          </div>
          <div className={'checkbContainer'}>
            <div>Saját hely mutatása felül:</div>
            <input
              type="checkbox"
              checked={ownEntryOnTop}
              onChange={(e) => {
                setOwnEntryOnTop(e.target.checked)
              }}
            />
          </div>
        </div>
        {sum && list ? (
          <>
            <div className={`${styles.sumRow}`}>
              <div />
              <div>
                <b>{'Összesen: '}</b>
              </div>
              <div>{sum.newQuestions.toLocaleString()}</div>
              <div>{sum.allQuestions.toLocaleString()}</div>
              <div>{sum.count.toLocaleString()}</div>
            </div>
            <div className={styles.headerRow}>
              <div>
                <b>{'Rank'}</b>
              </div>
              <div>{'Felhasználó ID'}</div>
              {Object.keys(selectOptions).map((listKey) => {
                const val = selectOptions[listKey]
                return (
                  <div
                    className={`${listKey === key && styles.selected}`}
                    key={listKey}
                  >
                    {val.name}
                  </div>
                )
              })}
            </div>
            <div className={styles.table}>
              {list.map((listItem, i) => {
                return (
                  <div
                    className={`${styles.row} ${
                      listItem.userId === selfUserId && styles.selfRow
                    }`}
                    key={i}
                  >
                    <div>{listItem.rank + 1}</div>
                    <div>{'#' + listItem.userId}</div>
                    {Object.keys(selectOptions).map((listKey) => {
                      const val = listItem[listKey]
                      return <div key={listKey}>{val}</div>
                    })}
                  </div>
                )
              })}
            </div>
          </>
        ) : (
          <LoadingIndicator />
        )}
      </div>
    </div>
  )
}
