import React, { PureComponent, CSSProperties, ComponentType, FC, ReactElement, ReactNode } from 'react';
import cls from 'classnames';
import PropTypes from 'prop-types';
import { cssClasses } from '@douyinfe/semi-foundation/skeleton/constants';
import { strings } from '@douyinfe/semi-foundation/avatar/constants';

import '@douyinfe/semi-foundation/skeleton/skeleton.scss';

export type BasicProps = {
    prefixCls?: string;
    className?: string;
    style?: CSSProperties;
    type?: string;
};

export interface ParagraphProps extends BasicProps {
    rows?: number;
}

export interface AvatarProps extends BasicProps {
    size?: typeof strings.SIZE[number];
}

export type GenericProps = BasicProps & AvatarProps;

const sizeSet = strings.SIZE;

const generator = <T extends BasicProps >(type: string) =>
    (BasicComponent: ComponentType<T>): FC<T> =>
        (props): ReactElement => <BasicComponent type={type} {...props} />;

class Generic extends PureComponent<GenericProps> {
    static propTypes = {
        type: PropTypes.string,
        prefixCls: PropTypes.string,
        style: PropTypes.object,
        className: PropTypes.string,
        size: PropTypes.oneOf(sizeSet),
    };

    static defaultProps = {
        prefixCls: cssClasses.PREFIX,
        size: 'medium'
    };

    render() {
        const { prefixCls, className, type, size, ...others } = this.props;
        const classString = cls(className, `${prefixCls}-${type}`, {
            [`${prefixCls}-${type}-${size}`]: type.toUpperCase() === 'AVATAR'
        });
        return React.createElement('div', { className: classString, ...others });
    }
}

export const Avatar = generator<AvatarProps>('avatar')(Generic);
export const Image = generator<BasicProps>('image')(Generic);
export const Title = generator<BasicProps>('title')(Generic);
export const Button = generator<BasicProps>('button')(Generic);

export class Paragraph extends PureComponent<ParagraphProps> {
    static propTypes = {
        rows: PropTypes.number,
        prefixCls: PropTypes.string,
        style: PropTypes.object,
        className: PropTypes.string,
    };

    static defaultProps = {
        prefixCls: cssClasses.PREFIX,
        rows: 4,
    };

    render(): ReactNode {
        const { prefixCls, className, style, rows } = this.props;
        const classString = cls(className, `${prefixCls}-paragraph`);
        return (
            <ul className={classString} style={style}>
                {[...Array(rows)].map((e, i) => <li key={i} />)}
            </ul>
        );
    }
}