#!/usr/bin/env python3
#
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Extracts compat_config.xml from built jar files and merges them into a single
XML file.
"""

import argparse
import collections
import sys
import xml.etree.ElementTree as ET
from zipfile import ZipFile

XmlContent = collections.namedtuple('XmlContent', ['xml', 'source'])

def extract_compat_config(jarfile):
    """
    Reads all compat_config.xml files from a jarfile.

    Yields: XmlContent for each XML file found.
    """
    with ZipFile(jarfile, 'r') as jar:
        for info in jar.infolist():
            if info.filename.endswith("_compat_config.xml"):
                with jar.open(info.filename, 'r') as xml:
                    yield XmlContent(xml, info.filename)

def change_element_tostring(element):
    s = "%s(%s)" % (element.attrib['name'], element.attrib['id'])
    metadata = element.find('meta-data')
    if metadata is not None:
        s += " defined in class %s at %s" % (metadata.attrib['definedIn'], metadata.attrib['sourcePosition'])
    return s

class ChangeDefinition(collections.namedtuple('ChangeDefinition', ['source', 'element'])):
    def __str__(self):
        return "  From: %s:\n    %s" % (self.source, change_element_tostring(self.element))

class ConfigMerger(object):

    def __init__(self, detect_conflicts):
        self.tree = ET.ElementTree()
        self.tree._setroot(ET.Element("config"))
        self.detect_conflicts = detect_conflicts
        self.changes_by_id = dict()
        self.changes_by_name = dict()
        self.errors = 0
        self.write_errors_to = sys.stderr

    def merge(self, xmlFile, source):
        xml = ET.parse(xmlFile)
        for child in xml.getroot():
            if self.detect_conflicts:
                id = child.attrib['id']
                name = child.attrib['name']
                this_change = ChangeDefinition(source, child)
                if id in self.changes_by_id.keys():
                    duplicate = self.changes_by_id[id]
                    self.write_errors_to.write(
                        "ERROR: Duplicate definitions for compat change with ID %s:\n%s\n%s\n" % (
                        id, duplicate, this_change))
                    self.errors += 1
                if name in self.changes_by_name.keys():
                    duplicate = self.changes_by_name[name]
                    self.write_errors_to.write(
                        "ERROR: Duplicate definitions for compat change with name %s:\n%s\n%s\n" % (
                        name, duplicate, this_change))
                    self.errors += 1

                self.changes_by_id[id] = this_change
                self.changes_by_name[name] = this_change
            self.tree.getroot().append(child)

    def _check_error(self):
        if self.errors > 0:
            raise Exception("Failed due to %d earlier errors" % self.errors)

    def write(self, filename):
        self._check_error()
        ET.indent(self.tree)
        self.tree.write(filename, encoding='utf-8', xml_declaration=True)

    def write_device_config(self, filename):
        self._check_error()
        self.strip_config_for_device().write(filename, encoding='utf-8', xml_declaration=True)

    def strip_config_for_device(self):
        new_tree = ET.ElementTree()
        new_tree._setroot(ET.Element("config"))
        for change in self.tree.getroot():
            new_change = ET.Element("compat-change")
            new_change.attrib = change.attrib.copy()
            new_tree.getroot().append(new_change)
        return new_tree

def main(argv):
    parser = argparse.ArgumentParser(
        description="Processes compat config XML files")
    parser.add_argument("--jar", type=argparse.FileType('rb'), action='append',
        help="Specifies a jar file to extract compat_config.xml from.")
    parser.add_argument("--xml", type=argparse.FileType('rb'), action='append',
        help="Specifies an xml file to read compat_config from.")
    parser.add_argument("--device-config", dest="device_config", type=argparse.FileType('wb'),
        help="Specify where to write config for embedding on the device to. "
        "Meta data not needed on the devivce is stripped from this.")
    parser.add_argument("--merged-config", dest="merged_config", type=argparse.FileType('wb'),
        help="Specify where to write merged config to. This will include metadata.")
    parser.add_argument("--allow-duplicates", dest="allow_duplicates", action='store_true',
        help="Allow duplicate changed IDs in the merged config.")

    args = parser.parse_args()

    config = ConfigMerger(detect_conflicts = not args.allow_duplicates)
    if args.jar:
        for jar in args.jar:
            for xml_content in extract_compat_config(jar):
                config.merge(xml_content.xml, "%s:%s" % (jar.name, xml_content.source))
    if args.xml:
        for xml in args.xml:
            config.merge(xml, xml.name)

    if args.device_config:
        config.write_device_config(args.device_config)

    if args.merged_config:
        config.write(args.merged_config)



if __name__ == "__main__":
    main(sys.argv)
