import React, { PropsWithChildren, useRef } from "react";
import { OSIcon, OSIconProps } from "../icon";
import { OSCSSProperties } from "../../types/react";
import { Tooltip } from "primereact/tooltip";
import { OSLabelProps } from "./props";

/**
 * Display a standardized label, with leading and trailing icons.
 * @classes `os-label` `os-label-icon-leading` `os-label-icon-trailing` `os-label-tooltip` `os-label-text`
 * 
 * @example
 * <OSLabel label="Example Message" leadingIcon={{identifier:"circle"}} inline />
 */
export function OSLabel({
    leading,
    trailing,
    leadingIcon,
    trailingIcon,
    label,
    justify,
    inline,
    weight,
    link,
    linkTarget,
    colour,
    size,
    tooltip,
    className,
    title,
    tooltipOptions,
    truncate,
    tag,
    ...props
}: OSLabelProps) {

    let Tag: React.ElementType<any, keyof React.JSX.IntrinsicElements> = "div";
    let TagOptions = null;
    if (typeof tag === "object") {
        const { type, ...tagOptions } = tag;
        Tag = type;
        TagOptions = tagOptions;
    } else {
        Tag = tag ?? "div";
    }
    const elementRef = useRef<any>(null);

    //Standard classes
    const classes = [
        "os-label",
        "items-center",
        "gap-1",
        "min-w-px",
    ];

    //Label classes
    const labelClasses = [
        "os-label-text"
    ];

    const styles: OSCSSProperties = { ...props.style };

    //Set inline
    classes.push(`${inline ? "inline-" : ""}flex`);

    //Set justification of label
    classes.push(`flex-row${justify === "right" ? "-reverse" : ""}`)

    //Set size
    size ? (styles.fontSize = size) : null;

    //Set weight
    if (weight) {
        if (typeof weight === "string") {
            classes.push(`font-${weight}`);
        } else {
            styles.fontWeight = weight;
        }
    }

    //Set colour
    colour ? (styles.color = colour) : null;

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

    if (truncate === undefined) {
        truncate = true;
    }
    if (truncate) {
        labelClasses.push("truncate");
    }

    const leadingClasses = "os-label-icon os-label-icon-leading";
    if (leading != undefined) {
        if (typeof leading === "string") {
            leading = <OSIcon className={leadingClasses} identifier={leading} />
        } else if (React.isValidElement(leading)) {
        } else if (leading != false) {
            leading = <OSIcon className={leadingClasses} {...leading as OSIconProps} />
        }
    } else if (leadingIcon != undefined) {
        if (typeof leadingIcon === "string") {
            leading = <OSIcon className={leadingClasses} identifier={leadingIcon} />
        } else if (leading != false) {
            leading = <OSIcon className={leadingClasses} {...leadingIcon as OSIconProps} />
        }
    }

    const trailingClasses = "os-label-icon os-label-icon-trailing";
    if (trailing != undefined) {
        if (typeof trailing === "string") {
            trailing = <OSIcon className={trailingClasses} identifier={trailing} />
        } else if (React.isValidElement(trailing)) {
        } else if (trailing != false) {
            trailing = <OSIcon className={trailingClasses} {...trailing as OSIconProps} />
        }
    } else if (trailingIcon != undefined) {
        if (typeof trailingIcon === "string") {
            trailing = <OSIcon className={trailingClasses} identifier={trailingIcon} />
        } else if (leading != false) {
            trailing = <OSIcon className={trailingClasses} {...trailingIcon as OSIconProps} />
        }
    }

    /**
     * Internal component to correctly handle link if present
     */
    function LabelTextWrapper(props: React.HTMLAttributes<HTMLElement> & PropsWithChildren) {
        return link
            ? <a {...props} ref={elementRef} href={link} target={linkTarget} />
            : <span {...props} ref={elementRef} />;
    }
    return (<>
        <Tag {...props} {...TagOptions} className={[...classes, className].join(" ")} style={styles}>
            {leading && leading}
            {(label !== undefined) && <LabelTextWrapper className={labelClasses.join(" ")} title={title}>{label}</LabelTextWrapper>}
            {trailing && trailing}
        </Tag>
        {tooltip && (elementRef !== null) && <Tooltip className="os-label-tooltip" target={elementRef as React.RefObject<HTMLElement>} {...tooltipOptions}>{tooltip}</Tooltip>}
    </>);
}