import React, { FC, forwardRef, memo }                                       from 'react';
import { cn }                                                                from '../../util/bem';
import { externalClasses, MediaPropsType }                                   from '../../util/externalClasses';
import { FrameExtensionUnionType, RadiusSizesType, SizeType, TextColorType } from '../../util/global-props';
import {  withMedia }                                                        from '../../util/media-merge';
import { Loader }                                                            from '../loader/loader.component';
import './wrapper.component.scss';

export type WrapperPropsType = {
    children?: React.ReactNode | string;
    className?: string;
    id?: string;

    row?: boolean;
    mediaColumn?: 'xsm' | 'sm' | 'md' | 'lg';
    align?: 'center' | 'right' | 'left' | 'stretch' | 'space-between' | 'space-around';
    valign?: 'top'|'center'|'bottom' | 'stretch';
    frame?: FrameExtensionUnionType;
    hoverEffect?: boolean;

    color?: TextColorType;
    padding?: SizeType;
    margin?: SizeType;
    fullWidth?: boolean;
    fullHeight?: boolean;
    maxWidth?: string;
    flex?: number | string ;
    styles?: React.CSSProperties;
    style?: React.CSSProperties;
    radius?: RadiusSizesType;
    overflow?: 'hidden' | 'scroll' | 'visible';
    loading?: boolean;
    loaderSize?: React.ComponentProps<typeof Loader>['size'];

    backgroundImage?: string;
    backgroundPosition?: ['left'| 'center' | 'right', 'top' | 'bottom' | 'center'];
    backgroundSize?: 'cover' | 'contain';

    /**
     * Used for remove last child margin inside wrapper
     * * */
    lastChildMargin?: boolean;
    innerRef?: React.Ref<HTMLDivElement>;
    onClick?: React.EventHandler<React.MouseEvent<HTMLDivElement, PointerEvent>>;
    onMouseDown?: React.EventHandler<React.MouseEvent<HTMLDivElement, PointerEvent>>;
    onMouseLeave?: React.EventHandler<React.MouseEvent<HTMLDivElement>>;
    onMouseEnter?: React.EventHandler<React.MouseEvent<HTMLDivElement>>;

    hide?: MediaPropsType;
    xsm?: WrapperPropsType;
    sm?: WrapperPropsType;
    md?: WrapperPropsType;
    lg?: WrapperPropsType;

}

const className = cn('wrapper');

export const Wrapper: FC<WrapperPropsType> = withMedia(memo(forwardRef((props, ref: React.Ref<HTMLDivElement>) => (
    <div
        ref={ props.innerRef }
        id={ props.id }
        className={ className({
            direction:       props.row ? 'row' : 'column',
            align:           props.align,
            valign:          props.valign,
            color:           props.color,
            frame:           props.frame,
            hover:           props.hoverEffect,
            padding:         props.padding,
            margin:          props.margin,
            flex:            props.flex,
            fullWidth:       props.fullWidth,
            fullHeight:      props.fullHeight,
            radius:          props.radius,
            overflow:        props.overflow,
            lastChildMargin: props.lastChildMargin,
            mediaColumn:     props.mediaColumn,
            loading:         props.loading

        }, null, props.className, externalClasses({ media: props.hide })) }
        // @ts-ignore
        style={ {
            maxWidth:           props.maxWidth,
            cursor:             props.onClick && 'pointer',
            backgroundImage:    props.backgroundImage && `url(${ props.backgroundImage })`,
            backgroundPosition: props.backgroundPosition && props.backgroundPosition[ 0 ] + props.backgroundPosition[ 1 ],
            backgroundSize:     props.backgroundSize,
            ...props.styles,
            ...props.style
        } }
        onClick={ props.onClick }
        onMouseEnter={ props.onMouseEnter }
        onMouseLeave={ props.onMouseLeave }
        onMouseDown={ props.onMouseDown }
    >
        { props.loading && <Loader color="white" size={ props.loaderSize } /> }
        { props.children }
    </div>
))));

Wrapper.defaultProps = { loaderSize: 'md' };

Wrapper.displayName = 'Wrapper';
