import type {
    MarkdownObject
} from "./type";
import {
    DEFAULT_VARIANTS
} from "./constant";

export const imageMarkdown = ({
    index,
    line
}: {
    index: number;
    line: string;
}): MarkdownObject => {
    const contentMatch = line.match(/\[(.*?)\]/);
    const imageContent = (contentMatch && contentMatch[1]) ? contentMatch[1] : "";
    const tmpLine = line.replace(/\[.*?\]/g, "");

    const urlMatch = tmpLine.match(/\((.*?)\)/);
    const imageURL = (urlMatch && urlMatch[1]) ? urlMatch[1] : "";
    const tmpLine2 = tmpLine.replace(/\((.*?)\)/, "");

    const imageSizeMatch = tmpLine2.match(/<(.*?)>/);
    const imageSize = (imageSizeMatch && imageSizeMatch[1]) ? imageSizeMatch[1].split("x").map(e => {
        return e.indexOf("%") !== -1 || e.indexOf("auto") !== -1 ? e : Number(e);
    }) : undefined;
    const tmpLine3 = tmpLine2.replace(/<(.*?)>/, "");

    const resizeModeMatch = tmpLine3.match(/--(.*?)--/);
    const resizeMode = (resizeModeMatch && resizeModeMatch[1]) ? resizeModeMatch[1] as "cover" | "contain" | "center" | "none" | "repeat" | "stretch" : undefined;

    return {
        resizeMode: resizeMode,
        content: imageContent,
        nativeType: "image",
        size: imageSize,
        type: "image",
        url: imageURL,
        key: index
    };
};

export const textMarkdown = ({
    index,
    type,
    line
}: {
    type: "# " | "## " | "### " | "#### " | "##### " | "###### " | "<p>";
    index: number;
    line: string;
}): MarkdownObject => {
    return {
        content: line.replace(type, ""),
        variant: DEFAULT_VARIANTS[type],
        nativeType: type,
        type: "text",
        key: index
    };
};

export const enterMarkdown = ({
    index,
    line
}: {
    index: number;
    line: string;
}): MarkdownObject => {
    const _line = line.replace("<br/>", "");

    return {
        variant: DEFAULT_VARIANTS["<br/>"],
        nativeType: "<br/>",
        content: _line,
        type: "space",
        key: index
    };
};

export const codeMarkdown = ({
    skippedIndices,
    index,
    lines
}: {
    skippedIndices: number[];
    lines: string[];
    index: number;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith("```")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const codeContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            variant: DEFAULT_VARIANTS["```"],
            content: codeContent,
            nativeType: "```",
            type: "code",
            key: index
        };
    }
};

export const centerMarkdown = ({
    skippedIndices,
    index,
    lines
}: {
    skippedIndices: number[];
    lines: string[];
    index: number;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith("</center>")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const centerContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            content: centerContent,
            nativeType: "center",
            type: "center",
            key: index
        };
    }
};

export const leftMarkdown = ({
    skippedIndices,
    index,
    lines
}: {
    skippedIndices: number[];
    lines: string[];
    index: number;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith("</left>")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const leftContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            content: leftContent,
            nativeType: "left",
            type: "left",
            key: index
        };
    }
};

export const rightMarkdown = ({
    skippedIndices,
    index,
    lines
}: {
    skippedIndices: number[];
    lines: string[];
    index: number;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith("</right>")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const rightContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            content: rightContent,
            nativeType: "right",
            type: "right",
            key: index
        };
    }
};

export const linkMarkdown = ({
    skippedIndices,
    linkStartRegex,
    index,
    lines,
    line
}: {
    skippedIndices: number[];
    linkStartRegex: RegExp;
    lines: string[];
    index: number;
    line: string;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith("</link>")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        const match = line.match(linkStartRegex);
        const href = match ? match[1] : "";

        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const linkContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            content: linkContent,
            nativeType: "link",
            type: "link",
            key: index,
            url: href
        };
    }
};

export const blockquoteMarkdown = ({
    skippedIndices,
    index,
    lines
}: {
    skippedIndices: number[];
    lines: string[];
    index: number;
}): MarkdownObject | void => {
    let endIndex = -1;

    for (let j = index + 1; j < lines.length; j++) {
        if (lines[j]?.startsWith(">>")) {
            endIndex = j;
            break;
        }
    }

    if (endIndex !== -1) {
        for (let k = index + 1; k <= endIndex; k++) {
            skippedIndices.push(k);
        }

        const quoteContent = lines.slice(index + 1, endIndex).join("\n");

        return {
            variant: DEFAULT_VARIANTS["<<"],
            content: quoteContent,
            type: "blockquote",
            nativeType: "<<",
            key: index
        };
    }
};

export const listMarkdown = ({
    isStarList,
    index,
    line
}: {
    isStarList: boolean;
    index: number;
    line: string;
}): MarkdownObject => {
    return {
        variant: DEFAULT_VARIANTS[isStarList ? "* " : "- "],
        nativeType: isStarList ? "* " : "- ",
        content: line.substring(2),
        type: "list",
        key: index
    };
};

export const parseMarkdown = (rawText: string): Array<MarkdownObject> => {
    const lines = rawText.split("\n");
    const skippedIndices: number[] = [];

    return lines.map((line, index) => {
        if (skippedIndices.includes(index)) {
            return {
                type: undefined,
                nativeType: "",
                content: "",
                key: index
            };
        }

        if (line.startsWith("# ")) return textMarkdown({
            type: "# ",
            index,
            line
        });

        if (line.startsWith("## ")) return textMarkdown({
            type: "## ",
            index,
            line
        });

        if (line.startsWith("### ")) return textMarkdown({
            type: "### ",
            index,
            line
        });

        if (line.startsWith("#### ")) return textMarkdown({
            type: "#### ",
            index,
            line
        });

        if (line.startsWith("##### ")) return textMarkdown({
            type: "##### ",
            index,
            line
        });

        if (line.startsWith("###### ")) return textMarkdown({
            type: "###### ",
            index,
            line
        });

        if (line.startsWith("<br/>") || line === "") return enterMarkdown({
            index,
            line
        });

        if (line.startsWith("```")) {
            const returnedData = codeMarkdown({
                skippedIndices,
                index,
                lines
            });

            if(returnedData) return returnedData;
        }

        if (line.startsWith("<center>")) {
            const returnedData = centerMarkdown({
                skippedIndices,
                index,
                lines
            });

            if(returnedData) return returnedData;
        }

        if (line.startsWith("<right>")) {
            const returnedData = rightMarkdown({
                skippedIndices,
                index,
                lines
            });

            if(returnedData) return returnedData;
        }

        if (line.startsWith("<left>")) {
            const returnedData = leftMarkdown({
                skippedIndices,
                index,
                lines
            });

            if(returnedData) return returnedData;
        }

        const linkStartRegex = /^<link\s+href=["'](.*?)["']>/;

        if (linkStartRegex.test(line)) {
            const returnedData = linkMarkdown({
                skippedIndices,
                linkStartRegex,
                index,
                lines,
                line
            });

            if(returnedData) return returnedData;
        }

        if (line.startsWith("<<")) {
            const returnedData = blockquoteMarkdown({
                skippedIndices,
                index,
                lines
            });

            if(returnedData) return returnedData;
        }

        const isStartWithImage = line.startsWith("[");

        if(isStartWithImage || line.startsWith("[")) return imageMarkdown({
            index,
            line
        });

        const isStarList = line.startsWith("* ");

        if (isStarList || line.startsWith("- ")) return listMarkdown({
            isStarList,
            index,
            line
        });

        return {
            variant: DEFAULT_VARIANTS["<p>"],
            nativeType: "<p>",
            content: line,
            type: "text",
            key: index
        };
    });
};
