import React, { useRef } from "react";
import { OSIcon } from "./OSIcon";
import { Tooltip } from "primereact/tooltip";
import { isIconSize, parseAnimation } from "./helpers";
import { OSIconProps, OSIconStackProps } from "./props";

/**
 * Wrapper component to allow layering of OSIcons.
 * 
 * Animations can be applied to this level to animate all icons in stack
 * 
 * @classes `os-icon-stack` `os-icon-stack-tooltip` `os-clickable`
 * 
 * @example
 * <OSIconStack size="2x" animation="bounce" tooltip="User">
 *  <OSIcon identifier="square"/>
 *  <OSIcon identifier="user" animation="shake"/>
 * </OSIconStack>
 *  
 * @see {@link OSIcon}
 */
export function OSIconStack({
    size,
    tooltip,
    children,
    tooltipOptions,
    animation,
    ...props
}: OSIconStackProps) {

    const elementRef = useRef<any>(null);

    const classes = ["os-icon-stack", "fa-stack"];
    const styles = { ...props.style };

    //Set size
    if (size) {
        if (isIconSize(size)) {
            classes.push(`fa-${size}`);
        } else {
            styles.fontSize = size;
        }
    }

    //Update children to obey stack
    const processedChildren = React.Children.map(children, (child, index) => {
        if (!React.isValidElement(child)) return null;

        if (child.type !== OSIcon) {
            return null;
        }

        const oldProps = (child.props as OSIconProps);
        const props: Partial<OSIconProps> = {};
        const newClasses = [oldProps.className];

        //Shrink top layers if not defined, otherwise adjust sizing to suit stack
        if (oldProps.size) {
            props.size = undefined;
            newClasses.push(`fa-stack-${oldProps.size}`);
        } else {
            newClasses.push(`fa-stack-${index === 0 ? "2x" : "1x"}`);
        }

        //If weighting not defined, set bottom layer to solid
        if (!oldProps.weight && index === 0) {
            newClasses.push(`fa-solid`);
        }

        //Invert colour of top layers if no colour defined
        if (!oldProps.colour && index !== 0) {
            newClasses.push(`fa-inverse`);
        }

        //Apply style class if clickable
        if (props.onClick) {
            classes.push("os-clickable");
        }

        props.className = newClasses.join(" ");
        return React.cloneElement(child as React.ReactElement<OSIconProps>, props)
    })

    //Handle animation
    parseAnimation(animation, classes, styles)

    return (<>
        <div {...props} ref={elementRef} className={classes.join(" ")} style={styles}>
            {processedChildren}
        </div>
        {tooltip && (elementRef !== null) && <Tooltip className="os-icon-stack-tooltip" target={elementRef as React.RefObject<HTMLElement>} {...tooltipOptions}>{tooltip}</Tooltip>}
    </>);
};