import POGOProtos from 'pogo-protos';

import React from 'react';
import { ContentRect, default as Measure } from 'react-measure';
import { FixedSizeList } from 'react-window';

import classNames from 'classnames';

import { IIndividualValues } from 'app/components/PokemonExplorer/types';
import { Grade, IStats } from 'app/models/Pokemon';

import * as styles from 'app/styles/LeagueStatsList.scss';

export interface ILeagueStatsListProps {
    activePokemonId : POGOProtos.Enums.PokemonId;
    activePokemonForm : POGOProtos.Enums.Form;
    activeIndividualValues : IIndividualValues;
    leagueStatsList : Array<IStats>;

    handleActivateLeagueStats : (stats : IStats) => void;
}

interface IState {
    activePokemonId : POGOProtos.Enums.PokemonId;
    activePokemonForm : POGOProtos.Enums.Form;
    hasSetActiveStats : boolean;
    listRef : React.RefObject<FixedSizeList>;
    activeIndex : number;
    dimensions : {
        width : number;
        height : number;
    };
}

interface IRowFactory {
    index : number;
    style : React.CSSProperties;
}

export class LeagueStatsList extends React.Component<ILeagueStatsListProps, IState> {

    public static getDerivedStateFromProps(nextProps : ILeagueStatsListProps, previousState : IState) {
        const nextState : IState = {
            ...previousState,
            activePokemonId: nextProps.activePokemonId,
            activePokemonForm: nextProps.activePokemonForm,
            activeIndex: -1,
        };
        const activeIvs = nextProps.activeIndividualValues;

        if (nextProps.activePokemonId !== previousState.activePokemonId || nextProps.activePokemonForm !== previousState.activePokemonForm) {
            if (previousState.listRef.current !== null) {
                previousState.listRef.current.scrollToItem(0);
            }

        } else if (activeIvs.level !== null && activeIvs.ivHp !== null && activeIvs.ivAtk !== null && activeIvs.ivDef !== null) {
            let activeIndex = previousState.activeIndex;
            if (activeIndex === -1) {
                // there is no current index, wich means the user is entering in the IVs by hand
                // now we will look through the list to see if we can find a match
                nextProps.leagueStatsList.some((stats, index) => {
                    if (activeIvs.ivHp === stats.ivHp &&
                        activeIvs.ivAtk === stats.ivAtk &&
                        activeIvs.ivDef === stats.ivDef &&
                        activeIvs.level === stats.level
                    ) {
                        activeIndex = index;
                        return true;
                    }
                    return false;
                });
            }

            if (activeIndex > -1 && !previousState.hasSetActiveStats) {
                // the current IVs belong to the stats at the active index, so scroll to active stats
                if (previousState.listRef.current !== null) {
                    previousState.listRef.current.scrollToItem(activeIndex, 'center');
                }
            }

            if (activeIndex === -1) {
                if (previousState.listRef.current !== null) {
                    previousState.listRef.current.scrollToItem(0);
                }
            }

            nextState.activeIndex = activeIndex;
        }

        return nextState;
    }

    constructor(props : ILeagueStatsListProps) {
        super(props);

        this.state = {
            activePokemonId: POGOProtos.Enums.PokemonId.MISSINGNO,
            activePokemonForm: POGOProtos.Enums.Form.FORM_UNSET,
            hasSetActiveStats: false,
            listRef: React.createRef(),
            activeIndex: -1,
            dimensions: {
                width: -1,
                height: -1,
            }
        };
    }

    public render() {
        const { width, height } = this.state.dimensions;
        const onResize = (contentRect : ContentRect) => {
            if (typeof contentRect.bounds !== 'undefined') {
                this.setState({ dimensions: contentRect.bounds });
            }
        };

        return (
            <div className={ styles.selectList }>
                <Measure
                    bounds={ true }
                    onResize={ onResize }
                >
                    {
                        ({ measureRef }) => (
                            <div ref={ measureRef }>
                                <FixedSizeList
                                    ref={ this.state.listRef }
                                    height={ height }
                                    itemCount={ this.props.leagueStatsList.length }
                                    itemSize={ 35 }
                                    width={ width }
                                >
                                    { this.rowFactory.bind(this) }
                                </FixedSizeList>
                            </div>
                        )
                    }
                </Measure>
            </div>
        );
    }

    private padString(value : string, length : number) {
        let output = value;
        for (let i = length - value.length; i > 0; i--) {
            output += String.fromCharCode(160);
        }
        return output;
    }

    private rowFactory({ index, style } : IRowFactory) {
        const activeIvs = this.props.activeIndividualValues;
        const stats = this.props.leagueStatsList[index];
        const css = classNames(
            'list-item', // global style
            styles.listItem,
            {
                active: activeIvs.level === stats.level &&
                    activeIvs.ivHp === stats.ivHp &&
                    activeIvs.ivAtk === stats.ivAtk &&
                    activeIvs.ivDef === stats.ivDef,
                highlight: this.state.activeIndex === index, // this css class currently does nothing
            }
        );
        const onClick = () => {
            this.props.handleActivateLeagueStats(stats);
            this.setState({
                hasSetActiveStats: true,
                activeIndex: index
            });
        };

        return (
            <a
                key={ index }
                style={ style }
                className={ css }
                onClick={ onClick }
            >
                <span>{ Grade[stats.speciesGrade] }</span>
                <span>{ this.padString(stats.cp.toString(), 4) }</span>
                <span>{ this.padString(stats.level.toString(), 4) }</span>
                <span>{ this.padString(stats.ivHp.toString(), 2) }</span>
                <span>{ this.padString(stats.ivAtk.toString(), 2) }</span>
                <span>{ this.padString(stats.ivDef.toString(), 2) }</span>
            </a>
        );
    }
}
