import React, { ChangeEvent, useContext, useState } from 'react'
import DatePicker from 'react-datepicker'
import { PageMarginLeftRight } from '../../style/PageMarginLeftRight'
import styled, { ThemeContext } from 'styled-components'
import { distance } from '../../style/sizes'
import 'react-datepicker/dist/react-datepicker.css'
import { InputWithLabel } from 'components/inputWithLabel/InputWithLabel'
import Select from 'components/select/Select'
import { ChartInfoBox } from 'components/chartInfoBox/ChartInfoBox'
import Button from 'components/button/Button'
import Input from 'components/input/Input'
import { useHistory, useParams } from 'react-router'
import { useEffect } from 'react'
import { Bar, BarChart, CartesianGrid, Label, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
import { chartColors } from 'style/chartColors'
import { ClipLoader } from 'react-spinners'

interface IBikePointDetails {
    id: string,
    commonName: string,
    diagrammData: IBikePointActivityMap,
    installDate: number,
    nbDocks: number

}
type IBikePointActivityMap = {[hourOfDay: number]: IBikePointActivityAtHourOfDay}

interface IBikePointActivityAtHourOfDay {
    avgNbRentals: number,
    avgNbReturns: number,
    avgNbTotal:   number

}

/**
 * This page contains details about a specific bike point.
 */
export const BikePointDetails = () => {
    const history = useHistory()

    const { bikePointId } = useParams<{bikePointId: string}>()

    const [startTimeStamp, setStartTimestamp] = useState(Date.UTC(2015, 0, 4))
    const [endTimeStamp, setEndTimeStamp] = useState(Date.UTC(2015, 0, 19))
    const [dayOfWeek, setDayOfWeek] = useState(0)
    const [averageActivity, setAverageActivity] = useState('avgNbRentals')
    const [maxValueYAxis, setValueYAxis] = useState(0)
    // to be adjusted
    const [bikePointDetails, setBikePointDetails] = useState<IBikePointDetails | undefined>(undefined)

    const [loadingState, setLoadingState] = useState(false)

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

    const fetchData = async () => {
        setLoadingState(true)
        const response = await fetch(`http://localhost:8081/api/bike-point-details/${bikePointId}?&from=${startTimeStamp / 1000}&to=${endTimeStamp / 1000}&day=${dayOfWeek}`)
        const jsonResponse = await response.json()
        //to be adjusted
        setBikePointDetails(jsonResponse.bikePointDetails)
        setLoadingState(false)
    }

    return (
        <PageMarginLeftRight>
            <StyledRow>
                <StyledButton onClick={() => history.push('/')}>Back home</StyledButton>
                <StyledButton onClick={() => history.push('/map')}>Back to map</StyledButton>
            </StyledRow>
            <StyledRow>
                <h2>{bikePointDetails?.commonName ?? '...'}</h2>
            </StyledRow>

                <StyledTextRow><StyledMinWidth>ID:</StyledMinWidth>{bikePointDetails?.id ?? '...'}</StyledTextRow>
                <StyledTextRow><StyledMinWidth>Install Date:</StyledMinWidth>{(bikePointDetails && new Date(bikePointDetails.installDate*1000).toDateString()) ?? '...'}</StyledTextRow>
                <StyledTextRow><StyledMinWidth>Number of Docks:</StyledMinWidth>{bikePointDetails?.nbDocks ?? '...'}</StyledTextRow>

            <StyledRow>
                <div>
                    <ChartInfoBox bold={true} description={'This bar chart shows the average count of chosen activity sorted by hour of day (0-23) for the chosen day of week in the selected time range.'}>
                        <StyledRow>
                            <InputWithLabel label={'Day of week'}>
                                <Select onChange={(event: ChangeEvent<HTMLSelectElement>) => setDayOfWeek(Number(event.target.value))}>
                                    <option value='0'>Sunday</option>
                                    <option value='1'>Monday</option>
                                    <option value='2'>Tuesday</option>
                                    <option value='3'>Wednesday</option>
                                    <option value='4'>Thursday</option>
                                    <option value='5'>Friday</option>
                                    <option value='6'>Saturday</option>
                                </Select>
                            </InputWithLabel>
                            <InputWithLabel label={'Average Activity'}>
                                <Select onChange={(event: ChangeEvent<HTMLSelectElement>) => setAverageActivity(event.target.value)}>
                                    <option value='avgNbRentals'>Rentals</option>
                                    <option value='avgNbReturns'>Returns</option>
                                    <option value='avgNbTotal'>Total</option>
                                </Select>
                            </InputWithLabel>
                        </StyledRow>
                        <StyledRow>
                            <InputWithLabel label={'From'}>
                                <DatePicker
                                    selected={new Date(startTimeStamp)}
                                    onChange={(date: Date) => setStartTimestamp(date.getTime())}
                                    dateFormat='yyyy/MM/dd'
                                    timeIntervals={5}
                                    customInput={<Input />}
                                />
                            </InputWithLabel>
                            <InputWithLabel label={'To'}>
                                <DatePicker
                                    selected={new Date(endTimeStamp)}
                                    onChange={(date: Date) => setEndTimeStamp(date.getTime())}
                                    dateFormat='yyyy/MM/dd'
                                    timeIntervals={5}
                                    customInput={<Input />}
                                />
                            </InputWithLabel>
                        </StyledRow>
                        <StyledRow>
                            <Button onClick={fetchData}>Apply Options</Button>&nbsp;&nbsp;&nbsp;{loadingState && <ClipLoader color={'white'} loading={loadingState}/>}
                        </StyledRow>
                    </ChartInfoBox>
                </div>
                <ResponsiveContainer width='100%' height={600}>
                    <BarChart
                        data={Object.entries(bikePointDetails?.diagrammData ?? {}).map(entry => {
                            let value

                            switch(averageActivity){
                                case 'avgNbRentals':
                                    value = entry[1].avgNbRentals
                                    if (value > maxValueYAxis) {setValueYAxis(value)}
                                    break
                                case 'avgNbReturns':
                                    value = entry[1].avgNbReturns
                                    if (value > maxValueYAxis) {setValueYAxis(value)}
                                    break
                                case 'avgNbTotal':
                                    value = entry[1].avgNbTotal
                                    if (value > maxValueYAxis) {setValueYAxis(value)}
                                    break

                            }
                         return  { hourOfDay: entry[0], value: value?.toFixed(2) }
                        })}
                        margin={{top: 5, right: 0, left: 0, bottom: 20,}}
                        barCategoryGap={15}
                    >
                        <CartesianGrid strokeDasharray='3 3'/>
                        <XAxis  dataKey='hourOfDay' textAnchor='start' height={50}>
                        <Label value='Hour of Day' offset={5} position='bottom' style={{fill: 'rgba(255, 255, 255, 1)'}}/>
                        </XAxis>
                        <YAxis allowDecimals={false} type='number' domain={[0, Math.round(maxValueYAxis+1)]}/>

                        <Tooltip contentStyle={{ backgroundColor: useContext(ThemeContext).colors.backgroundPrimary }}/>
                        <Legend layout='vertical' verticalAlign='top' align='center'/>
                        <Bar dataKey='value' fill={chartColors.cyan['50']} legendType='rect' name='Average Count' barSize={20} />
                    </BarChart>
                </ResponsiveContainer>
            </StyledRow>
            <StyledRow>

            </StyledRow>
        </PageMarginLeftRight>
    )
}

const StyledRow = styled.div`
    padding: ${distance.large};
    display: flex;
    flex-direction: row;
`
const StyledMinWidth = styled.div`  
    min-width: 10rem;
`
const StyledTextRow = styled.div`
    padding-left: ${distance.large};
    display: flex;
    flex-direction: row;
`
const StyledButton = styled(Button)`
    margin-right: ${distance.large};
` 
