#!/usr/bin/python

import codecs
import errno
import json
import os
import re
import sys
from sets import Set
from subprocess import call

UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)

placeholderRegex = re.compile("^<i18n:param>([a-zA-Z][a-zA-Z0-9_\\-\\.]*)</i18n:param>(.*)$", re.DOTALL)
dynamicRegex = re.compile(
    "^<i18n:dynamic project=\"tanker\" keyset=\"dynamic\" key=\"toggle\">[\\w\\s]*(.*?)[\\w\\s]*</i18n:dynamic>(.*)$", re.DOTALL)
conditionRegex = re.compile("<i18n:condition>\\w*<i18n:param>(.*?)</i18n:param>\\w*</i18n:condition>", re.DOTALL)
trueRegex = re.compile("(.*)<i18n:true>(.*?)</i18n:true>", re.DOTALL)
falseRegex = re.compile("(.*)<i18n:false>(.*?)</i18n:false>", re.DOTALL)

pluralRegex = re.compile(
    "^<i18n:dynamic project=\"tanker\" keyset=\"dynamic\" key=\"plural_adv\">(.*)</i18n:dynamic>(.*)$", re.DOTALL)
pluralCount = re.compile(".*<i18n:count>.*<i18n:param>(.+)</i18n:param>.*</i18n:count>.*", re.DOTALL)
pluralOne = re.compile(".*<i18n:one>(.*)</i18n:one>.*", re.DOTALL)
pluralSome = re.compile(".*<i18n:some>(.*)</i18n:some>.*", re.DOTALL)
pluralMany = re.compile(".*<i18n:many>(.*)</i18n:many>.*", re.DOTALL)
pluralNone = re.compile(".*<i18n:none>(.*)</i18n:none>.*", re.DOTALL)

javaTokenRegex = re.compile("^[a-zA-Z_][a-zA-Z0-9_]*$")

HTML_PREFIX = "HTML_"
TANKER_FORMATS_CLASS = "TankerFieldFormats"
KNOWN_LANGS = {"RU", "EN"}


class FieldImplementation(object):
    def providedParams(self, field):
        return [field.name]

    def getSetterArguments(self, field, html):
        return documentPartType(html) + " value"

    def writeSetterBody(self, javaSource, field, html):
        generateSetPlaceholder(javaSource, field.name, "value")


class DateTimeFieldImplementation(FieldImplementation):
    def providedParams(self, field):
        return [field.name + ".date", field.name + ".datetime"]

    def writeSetterBody(self, javaSource, field, html):
        convertTo = "Html" if html else "String"
        generateSetPlaceholder(javaSource, field.name + ".date",
                               TANKER_FORMATS_CLASS + ".dateTo" + convertTo + "(value)")
        generateSetPlaceholder(javaSource, field.name + ".datetime",
                               TANKER_FORMATS_CLASS + ".dateTimeTo" + convertTo + "(value)")

    def getSetterArguments(self, field, html):
        return "AbstractInstant value"


class UTMLabelsFieldImplementation(FieldImplementation):
    def providedParams(self, field):
        fn = field.name
        return [fn + "source", fn + "medium", fn + "campaign", fn + "content", fn + "labels"]

    def writeSetterBody(self, javaSource, field, html):
        fn = field.name
        generateSetPlaceholder(javaSource, fn + "source", convertString("value.getSource()", html))
        generateSetPlaceholder(javaSource, fn + "medium", convertString("value.getMedium()", html))
        generateSetPlaceholder(javaSource, fn + "campaign", convertString("value.getCampaign()", html))
        generateSetPlaceholder(javaSource, fn + "content", convertString("value.getContent()", html))
        generateSetPlaceholder(javaSource, fn + "labels", convertString("value.getLabelsInQuery()", html))

    def getSetterArguments(self, field, html):
        return "ru.yandex.webmaster3.core.notification.UTMLabels value"


class IntegerFieldImplementation(FieldImplementation):
    def writeSetterBody(self, javaSource, field, html):
        generateSetPlaceholder(javaSource, field.name, "mapper.apply(value)")
        javaSource.line("this.placeholders.putNumber(\"" + escapeJavaString(field.name) + "\", value);")

    def getSetterArguments(self, field, html):
        return "long value, LongFunction<" + documentPartType(html) + "> mapper"


SPECIAL_FIELDS = {
    "datetime": DateTimeFieldImplementation(),
    "string": FieldImplementation(),
    "utm": UTMLabelsFieldImplementation(),
    "integer": IntegerFieldImplementation(),
}


class FieldInfo(object):
    def __init__(self, name, type):
        self.name = name
        self.type = type


class KeySpec(object):
    def __init__(self, builderClassPrefix, fields):
        self.fieldsMap = {}
        self.fieldsArray = fields
        for field in fields:
            fieldImpl = SPECIAL_FIELDS[field.type]
            for fName in fieldImpl.providedParams(field):
                self.fieldsMap[fName] = field
        self.isStatic = len(fields) == 0
        if self.isStatic:
            self.builderClass = None
            self.namePrefix = None
        else:
            self.builderClass = builderClassPrefix + self.fieldsArray[0].name
            self.namePrefix = builderClassPrefix

    def getField(self, fieldName):
        return self.fieldsMap[fieldName] if self.fieldsMap.has_key(fieldName) else None


class JavaSource(object):
    def __init__(self, out):
        self.out = out
        self.depth = 0

    def line(self, text="", depthMod=0):
        if depthMod < 0:
            self.depth += depthMod
        if len(text) > 0:
            self.out.write("    " * self.depth)
            self.out.write(text)
        self.out.write("\n")
        if depthMod > 0:
            self.depth += depthMod


class TemplateEntry(object):
    def __init__(self, text, isPlaceholder, isCondition=False, isPlural=False):
        self.text = text
        self.isPlaceholder = isPlaceholder
        self.isCondition = isCondition
        self.isPlural = isPlural
        self.trueEntries = []
        self.falseEntries = []
        self.oneEntries = []
        self.someEntries = []
        self.manyEntries = []
        self.noneEntries = []

    def toJavaConstructor(self):
        if self.isCondition:
            result = "new TankerTemplateEntry.ConditionalEntry(\"" + escapeJavaString(self.text) + "\")"
            for entry in self.trueEntries:
                result += ".addTrueEntry(" + entry.toJavaConstructor() + ")"
            for entry in self.falseEntries:
                result += ".addFalseEntry(" + entry.toJavaConstructor() + ")"
            return result
        elif self.isPlaceholder:
            return "new TankerTemplateEntry.PlaceholderEntry(\"" + escapeJavaString(self.text) + "\")"
        elif self.isPlural:
            result = "new TankerTemplateEntry.PluralEntry(\"" + escapeJavaString(self.text) + "\")"
            for entry in self.oneEntries:
                result += ".addOneEntry(" + entry.toJavaConstructor() + ")"
            for entry in self.someEntries:
                result += ".addSomeEntry(" + entry.toJavaConstructor() + ")"
            for entry in self.manyEntries:
                result += ".addManyEntry(" + entry.toJavaConstructor() + ")"
            for entry in self.noneEntries:
                result += ".addNoneEntry(" + entry.toJavaConstructor() + ")"
            return result
        else:
            return "new TankerTemplateEntry.TextEntry(\"" + escapeJavaString(self.text) + "\")"


class Placeholder(object):
    def __init__(self, text):
        self.text = text


def mkdir(path):
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise


def fatalError(identity, message):
    print "Error processing " + identity + ": " + message
    exit(1)


def prepareJavaToken(identity, text):
    res = re.sub("[\\.\\-:\\=]", "_", text)
    if not javaTokenRegex.match(res):
        fatalError(identity, "cannot convert to java token: '" + text + "'")
    return res


def escapeJavaString(text):
    return text.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\"",
                                                                                                             "\\\"")


def processTemplate(identity, text, acc):
    if text == None:
        return TemplateEntry("", False)
    if isinstance(text, list):
        text = ''.join(text)
    if len(text) == 0:
        acc.append(TemplateEntry("", False))
        return
    while len(text) > 0:
        indexOfPH = text.find("<i18n:")
        if indexOfPH < 0:
            acc.append(TemplateEntry(text, False))
            return
        if indexOfPH > 0:
            acc.append(TemplateEntry(text[:indexOfPH], False))
            text = text[indexOfPH:]
        param = placeholderRegex.match(text)
        if param:
            acc.append(TemplateEntry(param.group(1), True))
            text = param.group(2)
        else:
            param = dynamicRegex.match(text)
            if param:
                condition = conditionRegex.match(param.group(1))
                trueValue = trueRegex.match(param.group(1))
                falseValue = falseRegex.match(param.group(1))
                text = param.group(2)
                if condition and trueValue and falseValue:

                    entry = TemplateEntry(condition.group(1), False, True)
                    processTemplate(identity, trueValue.group(2), entry.trueEntries)
                    processTemplate(identity, falseValue.group(2), entry.falseEntries)

                    acc.append(entry)
                else:
                    fatalError(identity, "unsupported dynamic syntax at \"" + param.group(1) + "\"")
            else:
                param = pluralRegex.match(text)
                if param:
                    content = param.group(1)
                    text = param.group(2)
                    count = pluralCount.match(content).group(1)
                    entry = TemplateEntry(count, False, False, isPlural=True)
                    processTemplate(identity, pluralOne.match(content).group(1), entry.oneEntries)
                    processTemplate(identity, pluralSome.match(content).group(1), entry.someEntries)
                    processTemplate(identity, pluralMany.match(content).group(1), entry.manyEntries)
                    processTemplate(identity, pluralNone.match(content).group(1), entry.noneEntries)
                    acc.append(entry)
                else:
                    fatalError(identity, "unsupported syntax at \"" + text + "\"")


def lang2Enum(lang):
    return "LanguageEnum." + lang.upper()


def loadSpec(specFileName):
    with codecs.open(specFileName, "r", "utf-8") as specFile:
        spec = json.load(specFile)
    return spec


def tankerSpecToFileName(tankerSpec):
    result = tankerSpec["project"] + "." + tankerSpec["branch"] + "." + tankerSpec["keyset"] + ".json"
    return result.replace(":", "$colon$")


def transposeTankerKeys(tankerKeys):
    key2Lang2Text = {}

    for lang, keys in tankerKeys.iteritems():
        for key, text in keys.iteritems():
            if (not key2Lang2Text.has_key(key)):
                key2Lang2Text[key] = {}
            key2Lang2Text[key][lang] = text
    return key2Lang2Text


def parseKeyFields(keySpec):
    if keySpec.has_key("fields"):
        fieldsSpec = keySpec["fields"]
    else:
        fieldsSpec = []
    result = []
    for field in fieldsSpec:
        result.append(FieldInfo(field["name"], field["type"] if field.has_key("type") else "string"))
    return result


def verifyTemplates(key, templates, keySpec):
    for lang, templateParts in templates.iteritems():
        print "Verifying key " + key + " in lang " + lang
        for part in templateParts:
            if part.isPlaceholder or part.isCondition or part.isPlural:
                fieldName = part.text
                fieldDesc = keySpec.getField(fieldName)
                if fieldDesc is None:
                    fatalError("key '" + key + "' lang '" + lang + "' field '" + fieldName + "'",
                               "not mentioned in spec")
                if part.isPlural:
                    if fieldDesc.type != "integer":
                        fatalError("key '" + key + "' lang '" + lang + "' field '" + fieldName + "'",
                                   "plural counter should be of type 'integer'")


def downloadKeysets(specFileName, tankerFilesDir):
    spec = loadSpec(specFileName)
    mkdir(tankerFilesDir)
    keysetsSet = Set([])
    for classSpec in spec:
        tankerSpec = classSpec["tanker"]
        keysetsSet.add(frozenset(tankerSpec.items()))

    for tankerSpecFrozen in keysetsSet:
        tankerSpec = dict(tankerSpecFrozen)
        downloadUrl = "https://tanker-api.yandex-team.ru/keysets/json/?project-id=" + tankerSpec["project"] + \
                      "&branch-id=" + tankerSpec["branch"] + \
                      "&keyset-id=" + tankerSpec["keyset"] + "&flat-keyset=1&all-forms=true&status=unapproved"
        jsonFileName = tankerFilesDir + "/" + tankerSpecToFileName(tankerSpec)
        tmpFileName = jsonFileName + ".tmp"
        call(["wget", downloadUrl, "-O", tmpFileName])
        with codecs.open(tmpFileName, "r", "utf-8") as jsonFile:
            # TODO: Workaround for WMC-1973
            # parsedJson = json.load(jsonFile)
            parsedJson = json.loads(jsonFile.read().replace("&amp;", "&"))
            with codecs.open(jsonFileName, "w", "utf-8") as out:
                json.dump(parsedJson, out, indent=2, sort_keys=True, ensure_ascii=False)
        os.remove(tmpFileName)


def documentPartType(html):
    return "HtmlNode" if html else "String"


def renderableType(html):
    return "HtmlNode" if html else "RenderableText"


def buildRenderableMethod(html):
    return "createHtmlNode" if html else "createRenderableText"


def generateSetPlaceholder(javaSource, placeholderName, value):
    javaSource.line("this.placeholders.put(\"" + escapeJavaString(placeholderName) + "\", " + value + ");")


def convertString(string, html):
    return "TankerFieldFormats.stringToHtml(" + string + ")" if html else string


def generateBuilderClass(javaSource, builder, html):
    builderNamePrefix = (HTML_PREFIX if html else "") + builder.namePrefix
    for idx, field in enumerate(builder.fieldsArray):
        first = idx == 0
        last = idx == (len(builder.fieldsArray) - 1)
        builderClassName = prepareJavaToken(field.name, builderNamePrefix + field.name)
        javaSource.line(
            "public static final class " + builderClassName + " extends AbstractTankerKeyBuilder<" + documentPartType(
                html) + "> {", 1)
        if first:
            javaSource.line("private " + builderClassName + "(List<TankerTemplateEntry> template) {", 1)
            javaSource.line("super(new TankerPlaceholders<>(), template);")
        else:
            javaSource.line("private " + builderClassName + "(TankerPlaceholders<" + documentPartType(
                html) + "> placeholders, List<TankerTemplateEntry> template) {", 1)
            javaSource.line("super(placeholders, template);")
        javaSource.line("}", -1)
        javaSource.line()

        fieldImpl = SPECIAL_FIELDS[field.type]
        returnType = renderableType(html) if last else builderNamePrefix + builder.fieldsArray[idx + 1].name
        returnType = prepareJavaToken(field.name, returnType)
        setterName = prepareJavaToken("field " + field.name, field.name)
        setterArgs = fieldImpl.getSetterArguments(field, html)
        returnExpression = "TankerKeyUtil." + buildRenderableMethod(html) + "(template, placeholders)" if last \
            else "new " + returnType + "(placeholders, template)"

        javaSource.line("public " + returnType + " " + setterName + "(" + setterArgs + ") {", 1)
        fieldImpl.writeSetterBody(javaSource, field, html)
        javaSource.line("return " + returnExpression + ";")
        # End method
        javaSource.line("}", -1)
        # End builder class
        javaSource.line("}", -1)


def generateDynamicKey(javaSource, key, keySpec, builderName, html):
    prefix = HTML_PREFIX if html else ""
    javaSource.line("public static final TankerDynamicKeyWithBuilder<" +
                    prefix + prepareJavaToken("class" + keySpec.builderClass, keySpec.builderClass) + "> " +
                    prefix + prepareJavaToken("key " + key, key) + " = ", 1)
    javaSource.line(builderName + ".build(" + prefix +
                    prepareJavaToken("key" + keySpec.builderClass, keySpec.builderClass) + "::new);")
    javaSource.line("", -1)


def generateEnumResolver(javaSource, commonSuperClass, enumClass, tankerKeys, html):
    keyPrefix = HTML_PREFIX if html else ""
    javaSource.line(
        "public static " + commonSuperClass + " fromEnum" + ("Html" if html else "") + "(" + enumClass + " value) {", 1)
    javaSource.line("switch(value.name()) {", 1)
    for key in tankerKeys.iterkeys():
        javaSource.line("case \"" + key + "\": return " + keyPrefix + prepareJavaToken("key " + key, key) + ";")
    javaSource.line(
        "default: throw new IllegalArgumentException(\"Enum value \" + value + \" have not matching tanker key\");")
    # End switch
    javaSource.line("}", -1)
    # End method
    javaSource.line("}", -1)


def generateCode(specFileName, tankerFilesDir, javaSourcesDir, javaTestSourcesDir, javaBasePackage):
    spec = loadSpec(specFileName)
    packageRelDir = javaBasePackage.replace(".", "/")
    javaPackageDir = javaSourcesDir + "/" + packageRelDir
    javaTestPackageDir = javaTestSourcesDir + "/" + packageRelDir
    mkdir(javaPackageDir)
    mkdir(javaTestPackageDir)
    for classSpec in spec:
        className = classSpec["class"]

        # Load keys
        with codecs.open(tankerFilesDir + "/" + tankerSpecToFileName(classSpec["tanker"]), "r",
                         "utf-8") as tankerKeysFile:
            tankerKeys = transposeTankerKeys(json.load(tankerKeysFile))

        # Filter (and substitute) keys by regexp
        if classSpec.has_key("regex"):
            regex = classSpec["regex"]
            pattern = regex["pattern"]
            subst = regex["subst"] if regex.has_key("subst") else "\\0"
            mappedKeys = {}
            for key, templates in tankerKeys.iteritems():
                if re.match(regex["pattern"], key):
                    mappedKeys[re.sub(pattern, subst, key)] = templates
            tankerKeys = mappedKeys

        builders = []

        fields = []
        haveDynKeys = False
        haveCustomDynKeys = False
        getKeySpec = (lambda key: keySpec)
        if "allKeys" in classSpec:
            keysSpecJson = classSpec["allKeys"] if classSpec.has_key("allKeys") else {}
            fields.extend(parseKeyFields(keysSpecJson))
            if len(fields) > 0:
                haveDynKeys = True

        if classSpec.has_key("keys"):
            keySpecsMap = {}
            for key, keysSpecJson in classSpec["keys"].iteritems():
                if keysSpecJson.has_key("tankerName"): # workaround for custom tankerName
                    tankerKeys[key] = tankerKeys[keysSpecJson["tankerName"]]
                if not tankerKeys.has_key(key):
                    fatalError("key '" + key + "'", "Key not found in tanker")
                keyFields = list(fields)
                customFields = parseKeyFields(keysSpecJson)
                keyFields.extend(customFields)
                if len(customFields) > 0:
                    haveCustomDynKeys = True
                if len(keyFields):
                    keySpec = KeySpec(key, keyFields)
                    builders.append(keySpec)
                    haveCustomDynKeys = True
                else:
                    keySpec = KeySpec("", [])
                keySpecsMap[key] = keySpec
            getKeySpec = (lambda key: keySpecsMap[key] if keySpecsMap.has_key(key) else None)

        if haveCustomDynKeys:
            commonSuperClass = "TankerDynamicKey"
            commonSuperClassHtml = commonSuperClass
        elif haveDynKeys:
            keySpec = KeySpec("Common", fields)
            builders.append(keySpec)
            commonSuperClass = "TankerDynamicKeyWithBuilder<" + keySpec.builderClass + ">"
            commonSuperClassHtml = "TankerDynamicKeyWithBuilder<" + HTML_PREFIX + keySpec.builderClass + ">"
        else:
            keySpec = KeySpec("", [])
            commonSuperClass = "TankerStaticKey"
            commonSuperClassHtml = commonSuperClass

        # Write java file
        javaSourceFileName = javaPackageDir + "/" + className + ".java"
        with codecs.open(javaSourceFileName, "w", "utf-8") as out:
            javaSource = JavaSource(out)
            javaSource.line("package " + javaBasePackage + ";")
            javaSource.line()
            javaSource.line("import ru.yandex.webmaster3.tanker.*;")
            javaSource.line("import ru.yandex.webmaster3.tanker.internal.*;")
            javaSource.line("import ru.yandex.webmaster3.core.notification.LanguageEnum;")
            javaSource.line("import ru.yandex.webmaster3.core.text.templates.RenderableText;")
            javaSource.line("import ru.yandex.webmaster3.core.text.templates.TextTemplate;")
            javaSource.line("import ru.yandex.webmaster3.tanker.digest.html.HtmlNode;")
            javaSource.line("import org.joda.time.base.AbstractInstant;")
            javaSource.line("import java.util.List;")
            javaSource.line("import java.util.function.LongFunction;")
            javaSource.line()
            javaSource.line("public final class " + className + " {", 1)
            toRemoveKeys = []
            for key, lang2Text in tankerKeys.iteritems():
                keySpec = getKeySpec(key)
                if keySpec is None:
                    toRemoveKeys.append(key)
                    continue
                templates = {}
                for lang, text in lang2Text.iteritems():
                    if lang.upper() in KNOWN_LANGS:
                        templateParts = []
                        processTemplate("lang '" + lang + "' key '" + key + "'", text, templateParts)
                        templates[lang] = templateParts

                verifyTemplates(key, templates, keySpec)

                if keySpec.isStatic:
                    if keySpec.builderClass is None:
                        javaSource.line(
                            "public static final TankerStaticKey " + prepareJavaToken("key " + key, key) + " = ", 1)
                        javaSource.line("TankerKeyUtil.newStaticBuilder()", 1)
                        for lang, text in templates.iteritems():
                            javaSource.line(".add(" + lang2Enum(lang) + ", \"" + escapeJavaString(text[0].text) + "\")")
                        javaSource.line(".build();", -1)
                    else:
                        javaSource.line("public static final TankerDynamicKeyWithBuilder<" +
                                        keySpec.builderClass + "> " + prepareJavaToken("key " + key, key) + " = ", 1)
                        javaSource.line("TankerKeyUtil.newStaticBuilder()", 1)
                        for lang, text in templates.iteritems():
                            javaSource.line(".add(" + lang2Enum(lang) + ", \"" + escapeJavaString(text) + "\")")
                        javaSource.line(".build(" + keySpec.builderClass + "::new);", -1)
                else:
                    builderName = prepareJavaToken("key " + key, key + "_BUILDER")
                    javaSource.line(
                        "private static final TankerKeyUtil.DynamicBuilder.LangBuilder " + builderName + " = TankerKeyUtil.newDynamicBuilder()",
                        1)
                    for lang, parts in templates.iteritems():
                        javaSource.line(".language(" + lang2Enum(lang) + ")")
                        for part in parts:
                            javaSource.line(".addEntry(" + part.toJavaConstructor() + ")")

                    javaSource.line(";")

                    generateDynamicKey(javaSource, key, keySpec, builderName, False)
                    generateDynamicKey(javaSource, key, keySpec, builderName, True)

                javaSource.line("", -1)

            for key in toRemoveKeys:
                tankerKeys.pop(key, None)
            for builder in builders:
                generateBuilderClass(javaSource, builder, False)
                generateBuilderClass(javaSource, builder, True)

            if classSpec.has_key("bindEnum"):
                enumClass = classSpec["bindEnum"]["enumClass"]
                generateEnumResolver(javaSource, commonSuperClass, enumClass, tankerKeys, False)
                if haveDynKeys or haveCustomDynKeys:
                    generateEnumResolver(javaSource, commonSuperClassHtml, enumClass, tankerKeys, True)
            # End main class
            javaSource.line("}", -1)
        if classSpec.has_key("bindEnum") and not classSpec["bindEnum"].has_key("disableTest"):
            bindEnumSpec = classSpec["bindEnum"]
            enumClass = bindEnumSpec["enumClass"]
            testClassName = className + "Test"
            javaTestSourceFileName = javaTestPackageDir + "/" + testClassName + ".java"
            testByPredicate = bindEnumSpec["testByPredicate"] if bindEnumSpec.has_key("testByPredicate") else None
            with codecs.open(javaTestSourceFileName, "w", "utf-8") as out:
                javaSource = JavaSource(out)
                javaSource.line("package " + javaBasePackage + ";")
                javaSource.line()
                javaSource.line("public final class " + testClassName + " {", 1)
                javaSource.line("")
                javaSource.line("@org.junit.Test")
                javaSource.line("public void shouldHaveKeysForAllEnumValues() {", 1)
                javaSource.line("for (" + enumClass + " value: " + enumClass + ".values()) {", 1)
                if not (testByPredicate is None):
                    javaSource.line("if (" + testByPredicate + "(value)) {", 1)
                javaSource.line(className + ".fromEnum(value);")
                if not (testByPredicate is None):
                    javaSource.line("}", -1)
                # End loop
                javaSource.line("}", -1)
                # End test method
                javaSource.line("}", -1)
                # End main class
                javaSource.line("}", -1)


def main():
    command = sys.argv[1]
    if command == "download":
        if len(sys.argv) != 4:
            print "Invalid number of arguments\n" + \
                  "Correct usage: download [spec file name] [tanker files dir]"
            exit(1)
        downloadKeysets(specFileName=sys.argv[2], tankerFilesDir=sys.argv[3])
    elif command == "build" or command == "download-and-build":
        if len(sys.argv) != 7:
            print "Invalid number of arguments\n" + \
                  "Correct usage: " + command + " [spec file name] [tanker files dir] [java sources dir] [java test sources dir] [java base package]"
            exit(1)
        specFileName = sys.argv[2]
        tankerFilesDir = sys.argv[3]
        if command == "download-and-build":
            downloadKeysets(
                specFileName=specFileName,
                tankerFilesDir=tankerFilesDir
            )
        generateCode(
            specFileName=specFileName,
            tankerFilesDir=tankerFilesDir,
            javaSourcesDir=sys.argv[4],
            javaTestSourcesDir=sys.argv[5],
            javaBasePackage=sys.argv[6]
        )
    else:
        print "Unknown command " + command
        exit(1)


if __name__ == '__main__':
    main()
