#!/usr/bin/env python3
# Simple and indolent text processor to do inline go function calling

import sys, re


files = sys.argv


class inline(object):
    def __init__(self, name):
        self.name = name
        self.receiver = ""
        self.args = []
        self.contents = []
        self.file = ""
        self.original = ""


inlines = {}
for file in sorted(files, reverse=True):
    contents = open(file).read().splitlines()
    i = 0
    name = ""
    while i < len(contents):
        line = contents[i]
        m = re.match(".*\/\/ \+inline-start", line)
        if m:
            m2 = re.match("^func\s*(\([\*\s\w]+\))?\s*(\w+)\(([^\)]*)\)", line)
            name = m2.group(2)
            tinline = inline(name)
            tinline.original = line.split("//")[0].strip().rstrip("{")
            tinline.file = file
            if m2.group(1):
                tinline.receiver = m2.group(1).split("(")[1].split(" ")[0]
            tinline.args = [arg.strip().split(" ")[0] for arg in m2.group(3).split(",")]
            inlines[name] = tinline
        else:
            if re.match(".*\/\/\s*\+inline-end", line):
                inlines[name].contents = "\n".join(inlines[name].contents)
                name = ""
            elif len(name) > 0:
                inlines[name].contents.append(line)
        i += 1


def do_inlining(text):
    contents = text.splitlines()
    buf = []
    i = 0
    while i < len(contents):
        line = contents[i]
        m = re.match("\s*\/\/\s*\+inline-call\s+([\w\.]+)\s+(.*)", line)
        if m:
            inlinet = inlines[m.group(1).split(".")[-1]]
            buf.append("// this section is inlined by go-inline")
            buf.append(
                "// source function is '{}' in '{}'".format(
                    inlinet.original, inlinet.file
                )
            )
            buf.append("{")
            if (
                len(inlinet.receiver) > 0
                and inlinet.receiver != m.group(1).split(".")[0]
            ):
                buf.append(
                    "{} := {}".format(
                        inlinet.receiver, ".".join(m.group(1).split(".")[0:-1])
                    )
                )

            callargs = [arg.strip() for arg in m.group(2).split(" ")]
            for j in range(len(callargs)):
                if inlinet.args[j] != callargs[j]:
                    buf.append("{} := {}".format(inlinet.args[j], callargs[j]))
            buf.append(do_inlining(inlinet.contents))
            buf.append("}")
        else:
            buf.append(line)
        i += 1
    return "\n".join(buf)


for file in files:
    if not file.startswith("_"):
        continue
    contents = open(file).read()
    with open(file.lstrip("_"), "w") as io:
        inlined = do_inlining(contents).split("\n")
        for i in range(len(inlined)):
            if i == 1:
                io.write("////////////////////////////////////////////////////////\n")
                io.write("// This file was generated by go-inline. DO NOT EDIT. //\n")
                io.write("////////////////////////////////////////////////////////\n")
            io.write(inlined[i])
            io.write("\n")
        io.write("\n")
