import React from 'react';
// do not use this example everywhere, no theming support in initial loading
// todo: add theming support for all other loaders
import injectSheetRaw from 'react-jss';
import {combineStyle, injectSheet, withTheme} from "../lib/theme";
import StyleGrid from "../lib/StyleGrid";

const toEm = (v) => (v / 16) + 'em';

const styles = {
    '@keyframes loading': {
        '0%': {
            top: '-1px',
            left: '-1px',
            width: '50px',
            height: '50px',
            opacity: 0,
        },
        '3%': {
            opacity: 0,
        },
        '50%': {
            opacity: 1,
        },
        '100%': {
            top: '23px',
            left: '23px',
            width: '2px',
            height: '2px',
            opacity: 0,
        }
    },
    wrapper: {
        display: 'block',
        position: 'relative',
        overflow: 'hidden',
        '&.center': {
            display: 'flex',
            margin: 'auto',
            [StyleGrid.smUp]: {
                margin: '0 auto',
            }
        }
    },
    item: {
        position: 'absolute',
        border: '2px solid #fff',
        opacity: '0',
        borderRadius: '50%',
        animation: 'loading 2.4s cubic-bezier(0, 0.3, 0.8, 1) infinite',
        '&:nth-child(2)': {
            animationDelay: '-1.2s',
        },
        '&:nth-child(3)': {
            animationDelay: '-0.8s',
        }
    }
};

class LoadingSmall extends React.Component {
    render() {
        // error is e.g. given from `Loadable` and is considered fatal error
        // errorWarning is is considered simple error
        const {
            classes, error, errorWarning, theme, name, center,
            width, height
        } = this.props;

        let styled = {wrapper: {}, item: {}};

        let style = {};
        if(this.props.style) {
            style.wrapper = this.props.style.wrapper || {};
            style.item = this.props.style.item || {};
        }

        let color = theme.textColor;
        if(errorWarning) {
            color = theme.errorColor;
        }

        // values are in px, calculated against 16px em base to build responsive loader
        const config = {
            items: 3,
            gap: 3,
            width: 6,
            widthActive: 8,
            height: 6,
            heightActive: 8,
            opacity: 0.2
        };

        styled.wrapper = combineStyle(styled.wrapper, style.wrapper);
        styled.item = combineStyle(styled.item, {});

        const dur = 0.925;
        const item = {
            attributeType: "XML",
            dur: dur + 's',
            repeatCount: "indefinite"
        };

        const widthAll = (config.items * (config.widthActive + config.gap)) - config.gap;

        let heightDiff = (config.heightActive - config.height) / 2;

        let widthDiff = (config.widthActive - config.width) / 2;

        return (
            error ? (
                    <React.Fragment>
                        <p>Fatal Error on Loading Component {name}</p>
                        <p>{JSON.stringify(error)}</p>
                    </React.Fragment>
                ) :
                <React.Fragment>
                    {this.props.children}

                    <div className={classes.wrapper + ' ' + (center ? 'center' : '')} style={styled.wrapper}>
                        <svg version="1.1" x="0px" y="0px"
                             width={toEm(width || widthAll)}
                             height={toEm(height || config.heightActive)}
                             viewBox={'0 0 ' + widthAll + ' ' + config.heightActive}
                             style={{display: 'block', margin: 'auto'}}>
                            <rect x="0"
                                  y={toEm(heightDiff)}
                                  width={toEm(config.width)}
                                  height={toEm(config.height)}
                                  fill={color}
                                  opacity={1}>
                                <animate attributeName="opacity" values={config.opacity + '; 1; ' + config.opacity} begin="0" {...item}/>
                                <animate attributeName="height" values={config.height + '; ' + config.heightActive + '; ' + config.height}
                                         begin={0} {...item}/>
                                <animate attributeName="width" values={config.width + '; ' + config.widthActive + '; ' + config.width}
                                         begin={0} {...item}/>
                                <animate attributeName="y" values={toEm(heightDiff) + '; 0; ' + toEm(heightDiff)} begin="0" {...item}/>
                                <animate attributeName="x" values={toEm(widthDiff) + '; 0; ' + toEm(widthDiff)} begin="0" {...item}/>
                            </rect>
                            <rect x={(config.widthActive + config.gap + widthDiff)}
                                  y={toEm(heightDiff)}
                                  width={toEm(config.width)}
                                  height={toEm(config.height)}
                                  fill={color}
                                  opacity={config.opacity}>
                                <animate attributeName="opacity" values={config.opacity + '; 1; ' + config.opacity} begin={(dur / 4) + 's'} {...item}/>
                                <animate attributeName="height" values={config.height + '; ' + config.heightActive + '; ' + config.height}
                                         begin={(dur / 4) + 's'} {...item}/>
                                <animate attributeName="width" values={config.width + '; ' + config.widthActive + '; ' + config.width}
                                         begin={(dur / 4) + 's'} {...item}/>
                                <animate attributeName="y" values={toEm(heightDiff) + '; 0; ' + toEm(heightDiff)} begin={(dur / 4) + 's'} {...item}/>
                                <animate attributeName="x" values={
                                    toEm(config.widthActive + config.gap + widthDiff) + '; ' +
                                    toEm((config.widthActive + config.gap)) + '; ' +
                                    toEm(config.widthActive + config.gap + widthDiff)
                                }
                                         begin={(dur / 4) + 's'} {...item}/>
                            </rect>
                            <rect x={(2 * (config.widthActive + config.gap)) + widthDiff}
                                  y={toEm(heightDiff)}
                                  width={toEm(config.width)}
                                  height={toEm(config.height)}
                                  fill={color}
                                  opacity={config.opacity}>
                                <animate attributeName="opacity" values={config.opacity + '; 1; ' + config.opacity} begin={(dur / 4 * 2) + 's'} {...item}/>
                                <animate attributeName="height" values={config.height + '; ' + config.heightActive + '; ' + config.height}
                                         begin={(dur / 4 * 2) + 's'} {...item}/>
                                <animate attributeName="width" values={config.width + '; ' + config.widthActive + '; ' + config.width}
                                         begin={(dur / 4 * 2) + 's'} {...item}/>
                                <animate attributeName="y" values={toEm(heightDiff) + '; 0; ' + toEm(heightDiff)} begin={(dur / 4 * 2) + 's'} {...item}/>
                                <animate attributeName="x"
                                         values={
                                             ((2 * (config.widthActive + config.gap)) + widthDiff) + '; ' +
                                             toEm((2 * (config.widthActive + config.gap))) + '; ' +
                                             ((2 * (config.widthActive + config.gap)) + widthDiff)
                                         }
                                         begin={(dur / 4 * 2) + 's'} {...item}/>
                            </rect>
                        </svg>
                    </div>
                </React.Fragment>
        )
    };
}

const LoadingRaw = injectSheetRaw(styles)(LoadingSmall);

export default withTheme(injectSheet(styles)(LoadingSmall));

export {LoadingRaw};