#!/usr/bin/awk

BEGIN {
    env = "none"
    stack_pointer = 0
    push(env)
}

# Function to push a value onto the stack
function push(value) {
    stack_pointer++
    stack[stack_pointer] = value
}

# Function to pop a value from the stack (LIFO)
function pop() {
    if (stack_pointer > 0) {
        value = stack[stack_pointer]
        delete stack[stack_pointer]
        stack_pointer--
        return value
    } else {
        return "empty"
    }
}

# Function to get last value in LIFO
function last() {
    return stack[stack_pointer]
}

function replaceInline(line,   result, start, end) {
    # Replace occurrences of **...** with <strong>...</strong>
    while (match(line, /\*\*([^*]+)\*\*/)) {
        start = RSTART
        end = RSTART + RLENGTH - 1
        # Build the result: before match, <strong>, content, </strong>, after match
        line = substr(line, 1, start-1) "<strong>" substr(line, start+2, RLENGTH-4) "</strong>" substr(line, end+1)
    }

    # Replace occurrences of *...* with <em>...</em>
    while (match(line, /\*([^*]+)\*/)) {
        start = RSTART
        end = RSTART + RLENGTH - 1
        # Build the result: before match, <em>, content, </em>, after match
        line = substr(line, 1, start-1) "<em>" substr(line, start+1, RLENGTH-2) "</em>" substr(line, end+1)
    }
  
    # Replace occurances of [link](url) with <a href="url">link</<a>
    while (match(line, /\[([^\]]+)\]\([^\)]+\)/)) {
        start = RSTART
        end = RSTART + RLENGTH - 1
        matched = substr($0, RSTART, RLENGTH)
        if (match(matched, /\[([^\]]+)\]/)) {
            matched_link = substr(matched, RSTART+1, RLENGTH-2) 
        }
        if (match(matched, /\([^\)]+\)/)) {
            matched_url = substr(matched, RSTART+1, RLENGTH-2)
        }
        # Build the result: before match, <a href="url">, content, </a>, after match
        line = substr(line, 1, start-1) "<a href=\"" matched_url "\">" matched_link "</a>" substr(line, end+1)
    }

    return line
}


function closeOne() {
    env = pop()
    print "</" env ">"
}

# Matching headers
/^#+ / {
    match($0, /#+ /);
    n = RLENGTH;
    print "<h" n-1 ">" substr($0, n + 1) "</h" n-1 ">" 
}

# Matching blockquotes
/^> / {
    env = last()
    if (env == "blockquote")
    {
        # In a blockquote block only print the text
        print substr($0, 3);
    } else {
        # Otherwise, init the blockquote block 
        push("blockquote")
        print "<blockquote>\n" substr($0, 3)
    }
}

# Matching unordered lists
/^[-+*] / {
    env = last()
    if (env == "ul" ) {
        # In a unordered list block, print a new item 
        print "<li>" substr($0, 3) "</li>" 
    } else {
        # Otherwise, init the unordered list block 
        push("ul")
        print "<ul>\n<li>" substr($0, 3) "</li>"
    }
}

# Matching ordered lists 
/^[0-9]+\./ {
    env = last()
    if (env == "ol") {
        # In a ordered list block, print a new item 
        print "<li>" substr($0, 4) "</li>"
    } else {
        # Otherwise, init the ordered list block 
        push("ol")
        print "<ol>\n<li>" substr($0, 4) "</li>"
    }
}

# Matching code block
/^(    |\t)/ {
    env = last()
    match($0, /(    |\t)/);
    n = RLENGTH;
    if (env == "code") {
        # In a code block, print a new item 
        print  substr($0, n+1)
    } else {
        # Otherwise, init the code block 
        push("pre")
        push("code")
        print "<pre><code>" substr($0, n+1)
    }
}


# Matching a simple paragraph
!/^(#|\*|-|\+|>|`|$|\t|    )/ {
    env = last() 
    if (env == "none") {
        # If no block, print a paragraph
        print "<p>" replaceInline($0) "</p>"
    } else if (env == "blockquote") {
        print $0
    }
}

$0 == "" {
    env = last()
    while (env != "none") {
        env = pop()
        print "</" env ">"
        env = last()
    }
}


END {
    env = last()
    while (env != "none") {
        env = pop()
        print "</" env ">"
        env = last()
    }
}