import { Tooltip } from "primereact/tooltip";
import { OSAvatarProps } from "./props";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { OSCSSProperties } from "../../types/react";
import { OSIcon } from "../icon";
import { OSLabel } from "../label";
import { Dialog } from "primereact/dialog";
import { Icon } from "../../types/icon";

/**
 * Display a standardized avatar, with fallback icon or text.
 * @classes `os-avatar` `os-avatar-image` `os-avatar-fallback` `os-avatar-fallback-icon` `os-avatar-fallback-text` `os-avatar-dialog-content`
 * 
 * @example
 * <OSLabel label="Example Message" leadingIcon={{identifier:"circle"}} inline />
 */
export function OSAvatar({
    image: imageSource,
    alt,
    label,
    size,
    tooltip,
    fallback,
    tooltipOptions,
    className,
    style,
    zoomable,
    foreground,
    ...props
}: OSAvatarProps) {
    const elementRef = useRef<any>(null);

    const [shouldShowDialog, setShouldShowDialog] = useState<boolean>(false);

    /** Internal handler of image to allow returning to fallback if image failed to load */
    const [image, setImage] = useState<string | undefined>(imageSource);
    const handleImageLoadError = useCallback(() => {
        console.warn(`Failed to load image "${imageSource}"`);
        setImage(undefined);
    }, [imageSource]);

    //Realtime reloading of image
    useEffect(() => {
        setImage(imageSource);
    }, [imageSource]);


    //Handle styling
    const classes = [
        "os-avatar",
        "flex",
        "place-content-center",
    ];
    const styles: OSCSSProperties = { overflow: "clip", ...style };

    if (size === "small") {
        styles.width = styles.height = "2rem";
        classes.push("small");
    } else if (size === "large") {
        styles.width = styles.height = "8rem";
        classes.push("large");
    } else {
        styles.width = styles.height = size;
    }
    return (<>
        {/** Dialog to show full-size image of avatar */}
        {zoomable && <Dialog className="os-avatar-dialog" header={label} visible={(shouldShowDialog && zoomable)} onHide={() => setShouldShowDialog(false)}>
            <div className="os-avatar-dialog-content flex justify-center items-center">
                <img
                    loading="eager"
                    src={image}
                    alt={alt}
                    style={{
                        width: "30rem",
                        height: "30rem",
                        maxHeight: "30rem",
                        marginBottom: "0.6rem",
                        objectFit: "cover" as "cover",
                        borderRadius: "5px",
                    }}
                />
            </div>
        </Dialog>}

        {/** Main Component */}
        <div {...props} ref={elementRef} className={[...classes, className].join(" ")} style={styles}>
            {image ? <img
                loading="eager"
                src={image}
                
                onError={handleImageLoadError}
                className={`os-avatar-image relative object-cover ${zoomable ? "cursor-pointer" : ""} w-full h-full`}
                onClick={() => {
                    setShouldShowDialog(true);
                }}
            />
                : React.isValidElement(fallback)
                    ? fallback
                    : typeof fallback === "string"
                        ? <OSLabel className="os-avatar-fallback os-avatar-fallback-text place-self-center-safe select-none" label={fallback} truncate={false} />
                        : <OSIcon {...fallback as Icon} tooltip={undefined} className={["os-avatar-fallback os-avatar-fallback-icon place-self-center", (fallback as Icon).className].join(" ")} />
            }
            {/* Foreground */}
            {foreground &&<div className="absolute w-full h-full grid">
                {foreground}
            </div>}
        </div>
        {tooltip && (elementRef !== null) && <Tooltip className="os-avatar-tooltip" target={elementRef} {...tooltipOptions}>{tooltip}</Tooltip>}
    </>);
}