import * as React from 'react';

export interface ProgressCircleProps {
    className?: string,
    percent?: number,
    prefixCls?: string,
    strokeColor?: string,
    strokeLinecap?: 'butt' | 'round' | 'square',
    strokeWidth?: number,
    style?: React.CSSProperties,
    trailColor?: string,
    trailWidth?: number,
    gapPosition?: 'top' | 'bottom' | 'left' | 'right',
    gapDegree?: number,
}

export class ProgressCircle extends React.Component<ProgressCircleProps, {}> {
    static defaultProps: ProgressCircleProps = {
        className: '',
        percent: 0,
        prefixCls: 'rc-progress',
        strokeColor: '#2db7f5',
        strokeLinecap: 'round',
        strokeWidth: 1,
        style: {},
        trailColor: '#D9D9D9',
        trailWidth: 1,
        gapPosition: "top",
        gapDegree: 0,
    }

    private prevTimeStamp: number;

    public path: SVGPathElement;

    constructor(props: ProgressCircleProps, context) {
        super(props, context);
    }

    componentDidUpdate() {
        const now = Date.now();
        this.path.style.transitionDuration = '0.3s, 0.3s';
        if (this.prevTimeStamp && now - this.prevTimeStamp < 100) {
            this.path.style.transitionDuration = '0s, 0s';
        }

        this.prevTimeStamp = Date.now();
    }

    private getPathStyles = () => {
        const { percent, strokeWidth, gapDegree = 0, gapPosition } = this.props;
        const radius = 50 - (strokeWidth / 2);
        let beginPositionX = 0;
        let beginPositionY = -radius;
        let endPositionX = 0;
        let endPositionY = -2 * radius;
        switch (gapPosition) {
            case 'left':
                beginPositionX = -radius;
                beginPositionY = 0;
                endPositionX = 2 * radius;
                endPositionY = 0;
                break;
            case 'right':
                beginPositionX = radius;
                beginPositionY = 0;
                endPositionX = -2 * radius;
                endPositionY = 0;
                break;
            case 'bottom':
                beginPositionY = radius;
                endPositionY = 2 * radius;
                break;
            default:
        }

        const pathString = `M 50,50 m ${beginPositionX},${beginPositionY} a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY} a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
        const len = Math.PI * 2 * radius;
        const trailPathStyle = {
            strokeDasharray: `${len - gapDegree}px ${len}px`,
            strokeDashoffset: `-${gapDegree / 2}px`,
            transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s',
        };
    
        const strokePathStyle = {
            strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
            strokeDashoffset: `-${gapDegree / 2}px`,
            transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s',
        };

        return { pathString, trailPathStyle, strokePathStyle };
    }

    render() {
        const { 
            prefixCls, 
            strokeWidth,
            trailWidth,
            strokeColor, 
            trailColor,
            strokeLinecap, 
            style, 
            className, 
            percent, 
            gapDegree, 
            gapPosition,
            children, 
            ...restProps
        } = this.props;
        const { pathString, trailPathStyle, strokePathStyle } = this.getPathStyles();
        
        return (
            <svg className={`${prefixCls}-circle ${className}`} viewBox="0 0 100 100" style={style} {...restProps}>
                <path
                    className={`${prefixCls}-circle-trail`}
                    d={pathString}
                    stroke={trailColor}
                    strokeWidth={trailWidth || strokeWidth}
                    fillOpacity="0"
                    style={trailPathStyle} />
                <path
                    className={`${prefixCls}-circle-path`}
                    d={pathString}
                    strokeLinecap={strokeLinecap}
                    stroke={strokeColor}
                    strokeWidth={strokeWidth}
                    fillOpacity="0"
                    ref={(path) => { this.path = path; }}
                    style={strokePathStyle} />
            </svg>
        );
    }
}
