import React from 'react';
import cx from 'classnames';
import * as glyphs12px from '../../icons/glyphs/12px';
import * as glyphs16px from '../../icons/glyphs/16px';
import * as glyphs24px from '../../icons/glyphs/24px';
import { upperFirst } from '../../utils';
import type { GlyphProps, SvgComponent } from '../../types';

export type GlyphName12PX = keyof typeof glyphs12px;
export type GlyphName16PX = keyof typeof glyphs16px;
export type GlyphName24PX = keyof typeof glyphs24px;
export type GlyphName = GlyphName12PX | GlyphName16PX | GlyphName24PX;

export type GlyphIconNamesSizeOptions =
    | { name: GlyphName12PX; size: 12 }
    | { name: GlyphName16PX; size: 16 }
    | { name: GlyphName24PX; size: 24 };

export type GlyphIconProps = GlyphProps &
    GlyphIconNamesSizeOptions & {
        testId?: string;
    };

const glyphs12pxComponents = glyphs12px as Record<GlyphName12PX, SvgComponent>;
const glyphs16pxComponents = glyphs16px as Record<GlyphName16PX, SvgComponent>;
const glyphs24pxComponents = glyphs24px as Record<GlyphName24PX, SvgComponent>;

export const GLYPH_ICONS_BY_SIZE = [
    ...Object.keys(glyphs12pxComponents).map((key): [GlyphName12PX, number] => [
        key as GlyphName12PX,
        12,
    ]),
    ...Object.keys(glyphs16pxComponents).map((key): [GlyphName16PX, number] => [
        key as GlyphName16PX,
        16,
    ]),
    ...Object.keys(glyphs24pxComponents).map((key): [GlyphName24PX, number] => [
        key as GlyphName24PX,
        24,
    ]),
].reduce(
    (result, [key, size]) => ({
        ...result,
        [key]: [...(result[key] ?? []), size],
    }),
    {} as Record<GlyphName, number[]>
);
export const getGlyphsBySize = () => GLYPH_ICONS_BY_SIZE;

const getIcon = ({ name, size }: GlyphIconProps): SvgComponent | undefined => {
    if (size === 12) return glyphs12pxComponents[name];
    else if (size === 16) return glyphs16pxComponents[name];
    else if (size === 24) return glyphs24pxComponents[name];
    return undefined;
};

/**
 * Glyphs are graphic symbols. They represent specific objects, concepts or actions.
 *
 * @type atom
 * @status live
 * @tags visuals
 */
export const GlyphIcon: React.FC<GlyphIconProps> = (props) => {
    const { name, size, inverse, className, style, testId } = props;

    const Icon = getIcon(props);
    if (!Icon) return null;

    const glyphClassName = `${upperFirst(name)}GlyphIcon`;

    return (
        <Icon
            data-testid={testId ?? glyphClassName}
            width={size}
            height={size}
            className={cx(`Icon GlyphIcon ${glyphClassName}`, { inverse }, className)}
            style={style}
        />
    );
};
