#!/usr/bin/python
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014 Intel, Inc.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; version 2 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

import xml.etree.ElementTree as ET
import sys
import os
import re
import json

#================================================================================
# class GitObsMapping
#================================================================================
class GitObsMapping:

    def __init__(self, prjdir):
        self.OBS_project = ""
        self.mapping = {"path":{}, "project":{}}
        self.branches = set()
        self.cur_path = ""
        self.cur_branches = ""
        self.cur_project = ""
        self.cur_default = 0
        self.cur_submission = "Y"
        self.cur_OBS_staging_project = ""
        self.cur_OBS_project = ""

        for root,dirs,files in os.walk(prjdir):
            for f in files:
                if f.endswith('.xml'):
                    fpath = os.path.join(root,f)
                    self.parse_tag(fpath)

    def _add_branches(self, branches):
        for b in branches.split(','):
            self.branches.add(b)

    def _add_mapping(self, proj_or_path, name, branches, attrib):
        for b in branches.split(','):
            #print "add mapping ", proj_or_path, name, b, attrib
            if b not in self.mapping[proj_or_path][name]:
                self.mapping[proj_or_path][name][b] = {}

            self.mapping[proj_or_path][name][b][attrib["OBS_project"]] = attrib

    def _parse_tag(self, xml):
        #####################################
        # <configure>
        if xml.tag == "configure":
            if not re.search("true", xml.attrib["enable"], re.IGNORECASE):
                #print "configure false!"
                return 0

        #####################################
        # <default>
        elif xml.tag == "default":
            self.cur_default = 1

            for child in xml:
                self._parse_tag(child)

            self.cur_default = 0

        #####################################
        # <virtual>
        elif xml.tag == "virtual":
            pass

        #####################################
        # <path>
        elif xml.tag == "path":
            path_name = xml.attrib["name"]

            old_submission = self.cur_submission
            if "submission" in xml.attrib:
                self.cur_submission = xml.attrib["submission"]

            self.cur_path = path_name
            if path_name not in self.mapping["path"]:
                self.mapping["path"][path_name]={}
                self.mapping["path"][path_name]["submission"] = self.cur_submission

            for child in xml:
                self._parse_tag(child)

            self.cur_path = ""
            self.cur_submission = old_submission

        #####################################
        # <branch>
        elif xml.tag == "branch":
            branches = xml.attrib["name"]

            self.cur_branches = branches
            self._add_branches(branches)

            if self.cur_path == "":
                if self.cur_project == "":
                    self.cur_OBS_project = xml.attrib["OBS_project"]
                    if "OBS_staging_project" in xml.attrib:
                        self.cur_OBS_staging_project = xml.attrib["OBS_staging_project"]

                    for child in xml:
                        self._parse_tag(child)

                    self.cur_OBS_project = ""
                    self.cur_OBS_staging_project = ""
                else:
                    attrib = {}
                    attrib["submission"] = self.cur_submission
                    attrib["OBS_project"] = xml.attrib["OBS_project"]
                    if "OBS_staging_project" in xml.attrib:
                        attrib["OBS_staging_project"] = xml.attrib["OBS_staging_project"]
                    if "OBS_package" in xml.attrib:
                        attrib["OBS_package"] = xml.attrib["OBS_package"]
                    self._add_mapping("project", self.cur_project, branches, attrib)

            else:
                # associated with path
                attrib = {}
                attrib["submission"] = self.cur_submission
                attrib["OBS_project"] = xml.attrib["OBS_project"]
                if "OBS_staging_project" in xml.attrib:
                    attrib["OBS_staging_project"] = xml.attrib["OBS_staging_project"]
                self._add_mapping("path", self.cur_path, branches, attrib)

            self.cur_branches = ""

        #####################################
        # <project>
        elif xml.tag == "project":
            project_name = xml.attrib["name"]

            self.cur_project = project_name

            old_submission = self.cur_submission
            if "submission" in xml.attrib:
                self.cur_submission = xml.attrib["submission"]

            if project_name not in self.mapping["project"]:
                self.mapping["project"][project_name] = {}
                self.mapping["project"][project_name]["submission"] = self.cur_submission

            if self.cur_branches == "":
                for child in xml:
                    self._parse_tag(child)
            else:
                attrib = {}
                attrib["submission"] = self.cur_submission
                attrib["OBS_project"] = self.cur_OBS_project
                attrib["OBS_staging_project"] = self.cur_OBS_staging_project

                attrib["OBS_package"] = project_name[project_name.rfind("/")+1:]
                if "OBS_package" in xml.attrib:
                    attrib["OBS_package"] = xml.attrib["OBS_package"]

                self._add_mapping("project", project_name, self.cur_branches, attrib)

            self.cur_project = ""
            self.cur_submission = old_submission

        #####################################
        # others...
        else:
            for child in xml:
                self._parse_tag(child)

        return 1

    def get_git_obs_map(self, proj, branch):
        return_obj = {}
        # first check if there is the same proj
        if proj in self.mapping["project"]:
            if self.mapping["project"][proj]["submission"] == "Y" and branch in self.mapping["project"][proj]:
                return_obj.update(self.mapping["project"][proj][branch])
                return return_obj

        # going up pathes
        path = "/"+proj
        while path != "/":
            path = path[0:path.rfind("/", 0, len(path)-1)+1]
            if path in self.mapping["path"]:
                if self.mapping["path"][path]["submission"] == "N":
                    return None
                if branch in self.mapping["path"][path]:
                    return_obj.update(self.mapping["path"][path][branch])
                    return return_obj
                return None

        return None

    def parse_tag(self, filename):
        if not os.path.isfile(filename):
            print "No such file: %s\n" % (filename)
            exit(0)
        mapping = ET.parse(filename).getroot()

        for child in mapping:
            if not self._parse_tag(child):
                break

    def dump(self):
        print self.mapping

    def print_json(self):
        print json.dumps(self.mapping)

    def print_to_file(self, filename):
        with open(filename, "w") as f:
            f.write(json.dumps(self.mapping))

    def print_pretty(self):
        for proj_name in self.mapping:
            print proj_name
            for proj in self.mapping[proj_name]:
                print proj
                print self.mapping[proj_name][proj]["submission"]
                for b in self.mapping[proj_name][proj]:
                    print b
                    print self.mapping[proj_name][proj][b]

    def print_branches(self):
        print json.dumps(list(self.branches))

    def get_branches(self):
        return self.branches

    def print_branches_to_file(self, filename):
        with open(filename, "w") as f:
            f.write(json.dumps(list(self.branches)))


