from JumpScale import j
# from SpecModelactorsGenerator import SpecModelactorsGenerator


class Specbase(j.tools.code.classGetBase()):

    def __init__(self, linenr):
        self.name = ""
        self.description = ""
        self.tags = ""
        self.comment = ""
        self.linenr = linenr

    def addDefaults(self):
        pass

    def getDefaultValue(self, type, value):
        if value.strip() == "" or value.strip() == "None":
            return None
        elif j.data.types.string.check(value):
            value = value.strip("\"")
        if type == 'int' and value:
            return int(value)
        elif type == 'bool' and value:
            return j.data.types.bool.fromString(value)
        return value


class SpecEnum(Specbase):

    def __init__(self, name, specpath, linenr):
        Specbase.__init__(self, linenr)
        self.name = name
        self.specpath = specpath
        self.appname = ""
        self.enums = []
        self.actorname = ""

    def _parse(self, parser, content):
        for line in content.split("\n"):
            if line.strip() != "":
                self.enums.append(line.strip())


class Specactor(Specbase):

    def __init__(self, name, descr, tags, specpath, linenr):
        Specbase.__init__(self, linenr)
        self.name = name
        self.description = descr
        self.tags = tags
        self.specpath = specpath
        self.appname = ""
        self.methods = []
        self.type = ""

    def _addItem(self, obj):
        self.methods.append(obj)

    def addDefaults(self):
        pass


class SpecactorMethod(Specbase):

    def __init__(self, linenr):
        Specbase.__init__(self, linenr)
        self.vars = []
        self.result = None

    def _parseFirstLine(self, parser, line):
        self.comment, self.tags, line = parser.getTagsComment(line)
        self.name = line.strip()

    def _parse(self, parser, content):

        content = parser.deIndent(content, self.linenr)
        linenr = self.linenr
        for line in content.split("\n"):
            linenr += 1
            line0 = line
            if line.strip() == "" or line.strip()[0] == "#":
                continue
            if line.find(":") != -1:
                comments, tags, line = parser.getTagsComment(line)
                errormsg = "Syntax error, right syntax var:$name $type,$defaultvalue,$description @tags #remarks"
                try:
                    varname, line = line.split(":", 1)
                except:
                    return parser.raiseError(errormsg, line0, linenr)
                if varname == "var":

                    if line.find(" ") == -1:
                        return parser.raiseError(errormsg, line0, linenr)
                    else:
                        varname, line = line.split(" ", 1)
                    try:
                        ttype, default, descr = line.split(",", 2)
                    except:
                        return parser.raiseError(errormsg, line0, linenr)

                    default = self.getDefaultValue(ttype, default)

                    spec = SpecactorMethodVar(
                        varname, descr, tags, linenr, default, ttype)
                    spec.comment = comments
                    self.vars.append(spec)
                elif varname == "result":
                    errormsg = "Syntax error, right syntax result:$type @tags #remarks"
                    if line.find(" ") == -1 and (line.find("@") != -1 or line.find("$") != -1):
                        return parser.raiseError(errormsg, line0, linenr)
                    if line.find(" ") == -1:
                        ttype = line
                    else:
                        ttype, line = line.split(" ", 1)
                    self.result = Specbase(linenr)
                    self.result.type = ttype
                    self.result.comment = comments
                else:
                    return parser.raiseError("Only var & result support on line, syntaxerror.", line0, linenr)


class SpecactorMethodVar(Specbase):

    def __init__(self, name, descr, tags, linenr, default, ttype):
        Specbase.__init__(self, linenr)
        self.name = name
        self.description = descr
        self.tags = tags
        self.defaultvalue = default
        self.ttype = ttype


class SpecModel(Specbase):

    def __init__(self, name, descr, tags, specpath, linenr):
        Specbase.__init__(self, linenr)
        self.name = name
        self.description = descr
        self.tags = tags
        self.specpath = specpath
        self.properties = []
        self.type = ""
        self.actorname = ""
        self.rootobject = False

    def _addItem(self, obj):
        self.properties.append(obj)

    def exists(self, propname):
        for prop in self.properties:
            if str(prop.name) == propname:
                return True
        return False

    def addDefaults(self):
        if self.type == "rootmodel":
            if not self.exists("id"):
                s = SpecModelProperty(0)
                s.type = 'int'
                s.name = 'id'
                s.description = 'Auto generated id @optional'
                self._addItem(s)


class SpecModelProperty(Specbase):

    def __init__(self, linenr):
        Specbase.__init__(self, linenr)
        self.default = None
        self.type = None

    def _parseFirstLine(self, parser, line):
        errormsg = "Syntax error, right syntax prop:$name $type,$defaultvalue,$description @tags #remarks"
        line0 = "prop:%s" % line
        if line.find(" ") == -1:
            return parser.raiseError(errormsg, line0, self.linenr)
        else:
            self.name, line = line.split(" ", 1)
        try:
            self.type, self.default, self.description = line.split(",", 2)
            self.default = self.getDefaultValue(self.type, self.default)
        except:
            return parser.raiseError(errormsg, line0, self.linenr)

    def _parse(self, parser, content):
        pass


class SpecBlock:
    """
    generic block of specs identified with starting with [...]
    can be multiple types
    """

    def __init__(self, parser, line, linenr, appname, actorname):
        self.appname = appname
        self.actorname = actorname
        self.descr = ""
        self.content = ""
        self.name = ""
        self.comment, self.tags, line = parser.getTagsComment(
            line)  # get @ out of the block
        # if line.find("@") != -1:
        # line=line.split("@")[0]
        # if line.find("#") != -1:
        # line=line.split("#")[0]
        line = line.replace("[", "")
        if line.find("]") == -1:
            return parser.raiseError("each [ on block should finish with ]", line, linenr)
        line = line.replace("]", "").strip()

      
  splitted = line.split(":")
        splitted = [item.strip().lower() for item in splitted]
        self.type = splitted[0]
        if len(splitted) == 1:
            self.name = ""
        elif len(splitted) == 2:
            self.name = splitted[1]
        else:
            return parser.raiseError(
                "each [...] on block need to be in format [$type:$name] or  [$type], did not find :", line, linenr)

        self.parser = parser
        self.startline = linenr
        self.items = 
[]

    def parse(self):

        self.content = self.parser.deIndent(self.content, self.startline)
        if self.type == "actor":
            ttypeId = "method"
            spec = None
            if len(list(j.core.specparser.specs.keys())) > 0 and self.type == "actor":
                key = "%s_%s" % (self.appname, self.actorname)
                if key in j.core.specparser.actornames:
                    spec = j.core.specparser.getactorSpec(
                        self.appname, self.actorname, False)
            if spec is None:
                spec = Specactor(self.name, self.descr, self.tags,
                                 self.parser.path, self.startline)
                spec.actorname = self.actorname
                spec.appname = self.appname
            if spec.appname not in j.core.specparser.app_actornames:
                j.core.specparser.app_