import {
    Back,
    Power1,
    TimelineMax,
} from 'gsap';
import ClassNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import {
    UI_CLASS_NAME,
} from '../../global/constants';
import withTheme from '../../styles/withTheme';

const propTypes = {
    className: PropTypes.string,
    color: PropTypes.oneOf(['backgroundColorHighlight', 'backgroundColorStatic']),
    dataTestId: PropTypes.string,
    id: PropTypes.string,
    size: PropTypes.number,
    style: PropTypes.shape({}),
    title: PropTypes.string,
    theme: PropTypes.shape({
        palette: PropTypes.shape({
            cyan: PropTypes.shape({}),
            grey: PropTypes.shape({}),
        }),
    }),
};

const BLOCK_CLASS = 'activity_indicator';

const defaultProps = {
    className: undefined,
    color: 'backgroundColorHighlight',
    dataTestId: `${UI_CLASS_NAME}-${BLOCK_CLASS}`,
    id: undefined,
    size: 68,
    style: {},
    theme: undefined,
    title: 'Loading',
};

const BAR_CLASS = `${BLOCK_CLASS}--bar`;
const BAR_HEIGHT = 68;
const CIRCLE_CLASS = `${BLOCK_CLASS}--circle`;
const DURATION_DOWN = 0.55;
const DURATION_UP = 0.3;
const CIRCLE_SIZE = 16;
const CIRCLE_UP_Y_POS = -(BAR_HEIGHT - CIRCLE_SIZE);

class ActivityIndicator extends React.PureComponent {
    constructor() {
        super();

        this.barTweenLeft = new TimelineMax();
        this.barTweenMiddle = new TimelineMax();
        this.barTweenRight = new TimelineMax();
        this.circleTweenLeft = new TimelineMax();
        this.circleTweenMiddle = new TimelineMax();
        this.circleTweenRight = new TimelineMax();
    }

    componentDidMount() {
        // const principleDefaultEase = CustomEase.create('custom', 'M0,0 C0.302,0.116 0.302,1 1,1')
        const barToUpOptions = {
            ease: Power1.easeOut, // eslint-disable-line no-undef
            height: BAR_HEIGHT,
            opacity: 1,
        };

        const barToDownOptions = {
            ease: Back.easeOut.config(1.5), // eslint-disable-line no-undef
            height: CIRCLE_SIZE,
            opacity: 0,
        };

        const circleToUpOptions = {
            ease: Power1.easeOut, // eslint-disable-line no-undef
            y: CIRCLE_UP_Y_POS,
        };

        const circleToDownOptions = {
            ease: Back.easeOut.config(1.5), // eslint-disable-line no-undef
            y: 0,
        };

        this.barTweenLeft.delay(0).set(
            `.${BAR_CLASS}-left`,
            {
                height: CIRCLE_SIZE,
                opacity: 0,
            },
        ).to(
            `.${BAR_CLASS}-left`,
            DURATION_UP,
            barToUpOptions,
        ).to(
            `.${BAR_CLASS}-left`,
            DURATION_DOWN,
            barToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);

        this.barTweenMiddle.delay(0.45).set(
            `.${BAR_CLASS}-middle`,
            {
                height: CIRCLE_SIZE,
                opacity: 0,
            },
        ).to(
            `.${BAR_CLASS}-middle`,
            DURATION_UP,
            barToUpOptions,
        ).to(
            `.${BAR_CLASS}-middle`,
            DURATION_DOWN,
            barToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);

        this.barTweenRight.delay(0.9).set(
            `.${BAR_CLASS}-right`,
            {
                height: CIRCLE_SIZE,
                opacity: 0,
            },
        ).to(
            `.${BAR_CLASS}-right`,
            DURATION_UP,
            barToUpOptions,
        ).to(
            `.${BAR_CLASS}-right`,
            DURATION_DOWN,
            barToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);

        this.circleTweenLeft.delay(0).set(
            `.${BAR_CLASS}-left`,
            {
                y: 0,
            },
        ).to(
            `.${CIRCLE_CLASS}-left`,
            DURATION_UP,
            circleToUpOptions,
        ).to(
            `.${CIRCLE_CLASS}-left`,
            DURATION_DOWN,
            circleToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);

        this.circleTweenMiddle.delay(0.45).set(
            `.${BAR_CLASS}-middle`,
            {
                y: 0,
            },
        ).to(
            `.${CIRCLE_CLASS}-middle`,
            DURATION_UP,
            circleToUpOptions,
        ).to(
            `.${CIRCLE_CLASS}-middle`,
            DURATION_DOWN,
            circleToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);

        this.circleTweenRight.delay(0.9).set(
            `.${BAR_CLASS}-right`,
            {
                y: 0,
            },
        ).to(
            `.${CIRCLE_CLASS}-right`,
            DURATION_UP,
            circleToUpOptions,
        ).to(
            `.${CIRCLE_CLASS}-right`,
            DURATION_DOWN,
            circleToDownOptions,
        )
            .repeat(-1)
            .repeatDelay(0.5);
    }

    render() {
        const {
            className,
            color,
            dataTestId,
            id,
            size,
            style,
            theme,
            title,
        } = this.props;

        const {
            palette: {
                cyan,
                grey,
            },
        } = theme;

        const rootClasses = ClassNames(
            'ui',
            BLOCK_CLASS,
            className,
        );

        const transformScaleDecimal = (1 / 68) * size;

        let backgroundColorStyle;

        switch (color) {
            case 'backgroundColorStatic':
                backgroundColorStyle = grey[400];

                break;

            case 'backgroundColorHighlight':
                backgroundColorStyle = cyan[500];

                break;
            default:
                break;
        }

        return (
            <div
                className={rootClasses}
                data-testid={dataTestId}
                id={id}
                style={{
                    ...style,
                    transform: `scale(${transformScaleDecimal})`,
                    transformOrigin: 0,
                }}
                title={title}
            >
                <div
                    className={`${BLOCK_CLASS}--left`}
                >
                    <div
                        className={`${CIRCLE_CLASS} ${CIRCLE_CLASS}-left`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />

                    <div
                        className={`${BAR_CLASS} ${BAR_CLASS}-left`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />
                </div>

                <div
                    className={`${BLOCK_CLASS}--middle`}
                >
                    <div
                        className={`${CIRCLE_CLASS} ${CIRCLE_CLASS}-middle`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />

                    <div
                        className={`${BAR_CLASS} ${BAR_CLASS}-middle`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />
                </div>

                <div
                    className={`${BLOCK_CLASS}--right`}
                >
                    <div
                        className={`${CIRCLE_CLASS} ${CIRCLE_CLASS}-right`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />

                    <div
                        className={`${BAR_CLASS} ${BAR_CLASS}-right`}
                        style={{
                            backgroundColor: backgroundColorStyle,
                        }}
                    />
                </div>
            </div>
        );
    }
}

ActivityIndicator.propTypes = propTypes;
ActivityIndicator.defaultProps = defaultProps;

export default withTheme(ActivityIndicator);
