#
# Copyright (C) 2017 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 values from the AndroidManifest.xml file."""
from __future__ import print_function

import argparse
import os.path
import xml.etree.ElementTree


def parse_args() -> argparse.Namespace:
    """Parse and return command line arguments."""
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "property",
        metavar="PROPERTY",
        choices=("minSdkVersion", "debuggable"),
        help="Property to extract from the manifest file.",
    )

    parser.add_argument(
        "manifest_file",
        metavar="MANIFEST_FILE",
        type=os.path.abspath,  # type: ignore
        help="Path to the AndroidManifest.xml file.",
    )

    return parser.parse_args()


def get_rpath_attribute(
    root: xml.etree.ElementTree.Element,
    element_path: str,
    attribute: str,
    default: str = "",
) -> str:
    """Returns the value of an attribute at an rpath.

    If more than one element exists with the same name, only the first is
    checked.

    Args:
        root: The XML element to search from.
        path: The path to the element.
        attribute: The name of the attribute to fetch.

    Returns:
        The attribute's value as a string if found, else the value of
        `default`.
    """
    ns_url = "http://schemas.android.com/apk/res/android"
    ns = {
        "android": ns_url,
    }

    elem = root.find(element_path, ns)
    if elem is None:
        return ""
    # ElementTree elements don't have the same helpful namespace parameter that
    # the find family does :(
    attrib_name = attribute.replace("android:", "{" + ns_url + "}")
    return str(elem.get(attrib_name, default))


def get_minsdkversion(root: xml.etree.ElementTree.Element) -> str:
    """Finds and returns the value of android:minSdkVersion in the manifest.

    Returns:
        String form of android:minSdkVersion if found, else the empty string.
    """
    return get_rpath_attribute(root, "./uses-sdk", "android:minSdkVersion", "")


def get_debuggable(root: xml.etree.ElementTree.Element) -> str:
    """Finds and returns the value of android:debuggable in the manifest.

    Returns:
        String form of android:debuggable if found, else the empty string.
    """
    debuggable = get_rpath_attribute(root, "./application", "android:debuggable", "")

    # Though any such manifest would be invalid, the awk script rewrote bogus
    # values to false. Missing attributes should also be false.
    if debuggable != "true":
        debuggable = "false"

    return debuggable


def main() -> None:
    args = parse_args()

    tree = xml.etree.ElementTree.parse(args.manifest_file)
    if args.property == "minSdkVersion":
        print(get_minsdkversion(tree.getroot()))
    elif args.property == "debuggable":
        print(get_debuggable(tree.getroot()))
    else:
        raise ValueError


if __name__ == "__main__":
    main()
