#!/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()
        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)
