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

import classNames from 'classnames';

import { CombatMoveStats, IPokemonMove } from 'app/models/Pokemon';

import { TypeIndicator } from './TypeIndicator';

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

export interface IMovesDropdownProps {
    menuLabel : string;
    movesById : CombatMoveStats;
    selectedMove : IPokemonMove | null;
    options : Array<IPokemonMove>;
    handleToggleOpen : (open : boolean) => void;
    handleChangeSelectedOption : (option : IPokemonMove) => void;
}

interface IState {
    isMenuOpen : boolean;
    listRef : React.RefObject<FixedSizeList>;
    dimensions : {
        width : number;
        height : number;
    };
}

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

export class MovesDropdown extends React.Component<IMovesDropdownProps, IState> {

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

        this.state = {
            isMenuOpen: false,
            listRef: React.createRef(),
            dimensions: {
                width: -1,
                height: -1,
            }
        };
    }

    public render() {
        const {
            menuLabel,
            movesById,
            selectedMove,
            options,
        } = this.props;
        const {
            isMenuOpen,
        } = this.state;

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

        const wrapperCss = classNames(
            'nes-select',
            'dropdown',
            styles.wrapper,
        );
        const menuCss = classNames(
            'nes-container',
            styles.menu,
        );

        let moveName = 'Select a move';
        if (selectedMove !== null) {
            const moveStats = movesById.get(selectedMove.id);
            if (moveStats) {
                moveName = moveStats.name;
            } else {
                moveName = 'UNKNOWN MOVE';
            }
        }
        return (
            <React.Fragment>
                <div
                    className={ wrapperCss }
                    onClick={ this.toggleMenu }
                >
                    { moveName }
                </div>
                { isMenuOpen &&
                    <div className={ menuCss }>
                        <h3 className="title">{ menuLabel }</h3>
                        <Measure
                            bounds={ true }
                            onResize={ onResize }
                        >
                            {
                                ({ measureRef }) => (
                                    <div ref={ measureRef }>
                                        <FixedSizeList
                                            ref={ this.state.listRef }
                                            height={ height }
                                            itemCount={ options.length }
                                            itemSize={ 35 }
                                            width={ width }
                                        >
                                            { this.rowFactory.bind(this) }
                                        </FixedSizeList>
                                    </div>
                                )
                            }
                        </Measure>
                    </div>
                }
            </React.Fragment>
        );
    }

    private readonly toggleMenu = () => {
        const isMenuOpen = !this.state.isMenuOpen;
        this.setState({
            isMenuOpen,
        });
        this.props.handleToggleOpen(isMenuOpen);
    }

    private rowFactory({ index, style } : IRowFactory) {
        const {
            movesById,
            selectedMove,
            options,
        } = this.props;
        const move = options[index];
        const moveStats = movesById.get(move.id);
        const css = classNames(
            'list-item', // global style
            styles.listItem,
            {
                active: selectedMove && selectedMove.id === move.id,
            }
        );
        const typeCss = classNames({
            [styles.legacy]: move.isLegacy
        });
        const onClick = () => {
            this.props.handleChangeSelectedOption(move);
            this.toggleMenu();
        };

        return (
            <React.Fragment>
                { moveStats &&
                    <a
                        key={ index }
                        style={ style }
                        className={ css }
                        onClick={ onClick }
                    >
                        <span>{ moveStats.name }</span>
                        <TypeIndicator className={ typeCss } type={ moveStats.type } />
                    </a>
                }
            </React.Fragment>
        );
    }
}
