import React from 'react';
import { ElementType } from 'react';
import { classNamesTailwind } from '../../utils/theme';
import { parse, HTMLElement, NodeType, Node } from 'node-html-parser';
import { motion, Variants } from 'framer-motion';
import TextAnimated from '../TextAnimated';

export interface BoldTitleAnimatedProps {
    html: string | null;
    as?: ElementType;
    className?: string;
    variantsTitle?: Variants;
    variantsLine?: Variants;
    variantsLetter?: Variants;
}

export type Line =
    | {
          type: 'break';
      }
    | { type: 'text'; text: string; bold: boolean };

const reduceParsed = (html: HTMLElement, bold?: boolean): Line[] => {
    return (html.childNodes as HTMLElement[]).reduce((a, c) => {
        if (c.nodeType === NodeType.TEXT_NODE) {
            return [...a, { type: 'text', text: c.text, bold: !!bold }];
        }

        if (c.nodeType === NodeType.ELEMENT_NODE && c.tagName === 'BR') {
            return [...a, { type: 'break' }];
        }

        if (c.nodeType === NodeType.ELEMENT_NODE && c.childNodes && (c.tagName === 'B' || c.tagName === 'STRONG')) {
            return [...a, ...reduceParsed(c, true)];
        }

        if (c.nodeType === NodeType.ELEMENT_NODE && c.childNodes && c.childNodes.length > 0) {
            return [...a, ...reduceParsed(c)];
        }

        return a;
    }, [] as Line[]);
};

const BoldTitleAnimated = ({
    as = 'h3',
    html,
    className,
    variantsTitle = {
        initial: {},
        animate: { transition: { staggerChildren: 0.3 } }
    },
    variantsLine = {
        initial: {},
        animate: { transition: { staggerChildren: 0.025 } }
    },
    variantsLetter = {
        initial: {
            y: '100%',
            opacity: 0,
            transition: { ease: [0.455, 0.03, 0.515, 0.955], duration: 0.85 }
        },
        animate: {
            y: 0,
            opacity: 1,
            transition: { ease: [0.455, 0.03, 0.515, 0.955], duration: 0.3 }
        }
    }
}: BoldTitleAnimatedProps) => {
    if (!html) {
        return null;
    }

    const lines: Line[][] = reduceParsed(parse(html)).reduce(
        (a, c) => {
            const last = a.length - 1;

            if (c.type === 'break') {
                a.push([]);
            } else {
                a[last] = [...a[last], c];
            }

            return a;
        },
        [[]] as Line[][]
    );

    return (
        <motion.div className={className} variants={variantsTitle} animate="animate" initial="initial">
            {lines.map((line) => (
                <TextAnimated className="block" as={as} variantsLetter={variantsLetter} variantsLine={variantsLine} line={line} />
            ))}
        </motion.div>
    );
};

export default BoldTitleAnimated;
