#!/usr/bin/python3

import sys
import html

# Check if there is pipe input
if not sys.stdin.isatty():
    hasPipe = True
else:
    hasPipe = False

helpmsg = """\
USAGE
    elfdiff [input_file] [-o output_file]

OPTIONS
    -o [output_file]
        Saves produced diff HTML file to the specified file.
        If not given, stdout is used.

EXAMPLES
    Using arguments:
        git diff --word-diff=plain > diff.txt
        elfdiff diff.txt -o diff.html

    Using pipe:
        git diff --word-diff=plain | elfdiff > diff.html"""

# Parse options
if sys.argv.count("-o") > 0:
    idx = sys.argv.index("-o")
    outputFile = open(sys.argv[idx+1], "w+")
    sys.argv.pop(idx)
    sys.argv.pop(idx)
else:
    outputFile = sys.stdout

if sys.argv.count("-h") > 0:
    print(helpmsg)
    sys.exit(0)

if hasPipe:
    text = sys.stdin.read()
else: # Has arguments instead
    try:
        text = open(sys.argv[1]).read()
    except IndexError:
        print(helpmsg)
        sys.exit(1)

htmlText = """
<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
        <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em" crossorigin="anonymous"></script>
        <style>
            .rem {
                background-color: #F003;
            }
            .add {
                background-color: #0F03;
            }
        </style>
    </head>
    <body>
        <div class="container text-justify">"""

# Add first paragraph
htmlText += "<p>"

# Parse each line separately
for line in text.split("\n"):
    # Excape whole line, and change spaces to nbsp
    line = html.escape(line)
    line = line.replace("  ", " &nbsp")
    line = line.replace("&nbsp ", "&nbsp&nbsp")
    line = line.replace("\t", " &nbsp&nbsp&nbsp")

    # Check if there was a removal or an addition for that line (from git diff)
    hasRemove = line.find("[-") >= 0
    hasAdd    = line.find("{+") >= 0

    # Create a line with only the removals
    if hasRemove:
        remLine = line

        # Remove text within {+ +}
        while remLine.find("{+") >= 0:
            beg = remLine.find("{+")
            end = remLine.find("+}")
            if beg < 0 or end < 0:
                sys.stderr.write("Found unmatching {+ +}. Output HTML might be weird.\n")
                break
            remLine = remLine[:beg] + remLine[end+2:]

        # Add red colors for the text within [- -]
        remLine = remLine.replace("[-", """<span style="background-color: tomato; text-decoration: line-through;">""")
        remLine = remLine.replace("-]", """</span>""")

    # Create a line with only the additions
    if hasAdd:
        addLine = line

        # Remove text within [- -]
        while addLine.find("[-") >= 0:
            beg = addLine.find("[-")
            end = addLine.find("-]")
            if beg < 0 or end < 0:
                sys.stderr.write("Found unmatching [- -]. Output HTML might be weird.\n")
                break
            addLine = addLine[:beg] + addLine[end+2:]

        # Add green colors for text within {+ +}
        addLine = addLine.replace("{+", """<span style="background-color: #5fdd00;">""")
        addLine = addLine.replace("+}", """</span>""")

    # Add line or lines to the html object
    if len(line) == 0:
        # Open new paragraph
        htmlText += "</p><p>"
    elif hasRemove and hasAdd:
        htmlText += """<span class="rem">""" + remLine + """</span><br><span class="add">""" + addLine + "</span><br><br>\n"
    elif hasRemove:
        htmlText += """<span class="rem">""" + remLine + "</span><br><br>\n"
    elif hasAdd:
        htmlText += """<span class="add">""" + addLine + "</span><br><br>\n"
    else:
        htmlText += line + "<br>\n"

htmlText += """</p>
        </div>
    </body>
</html>"""

outputFile.write(htmlText)
