#!/usr/bin/env python3
#
# Copyright (C) 2021 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.
#

import argparse
from dataclasses import dataclass
from pathlib import Path
import re
import sys
from typing import List, Optional


SIMPLEPERF_DIR = Path(__file__).absolute().parent
AOSP_DIR = SIMPLEPERF_DIR.parents[2]
ART_NATIVE_METHOD_DIR = AOSP_DIR / 'art' / 'runtime' / 'native'
OUTPUT_FILE = SIMPLEPERF_DIR / 'art_jni_method_table.h'


def get_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="generate art jni methods")
    parser.add_argument('--check-only', action='store_true',
                        help='only check if the art jni methods have changed')
    return parser.parse_args()


@dataclass
class ArtJniMethod:
    # like java.long.reflect.Method
    class_name: str
    # like invoke
    java_method_name: str
    # like Method_invoke
    native_method_name: str


class ArtJniMethodParser:
    def __init__(self):
        self.class_name_pattern = re.compile(r'REGISTER_NATIVE_METHODS\(\"(.+?)\"\)')
        # from libnativehelper/include_platform_header_only/nativehelper/jni_macros.h
        self.method_patterns = []
        self.overload_method_patterns = []
        for name in ['NATIVE_METHOD', 'FAST_NATIVE_METHOD', 'CRITICAL_NATIVE_METHOD']:
            method_s = r'\(\s*(\w+)\s*,\s*(\w+)'
            self.method_patterns.append(re.compile(r'\s+' + name + method_s))
            self.method_patterns.append(re.compile(r'\s+' + name + 'AUTOSIG' + method_s))
            overload_s = r'\(\s*(\w+)\s*,\s*(\w+)\s*,[^,]*,\s*(\w+)'
            self.overload_method_patterns.append(re.compile(r'\s+OVERLOADED_' + name + overload_s))
        self.static_function_pattern = re.compile(r'static\s+\w+\s+(\w+)\(')
        self.file_path = None

    def parse_methods(self, file_path: Path) -> List[ArtJniMethod]:
        self.file_path = file_path
        text = file_path.read_text()
        class_name = self._get_class_name(text)
        if not class_name:
            return []
        methods = self._get_methods(text, class_name)
        self._check_methods(text, methods)
        return methods

    def _get_class_name(self, text: str) -> Optional[str]:
        """ Return class name like "dalvik.system.BaseDexClassLoader". """
        m = self.class_name_pattern.search(text)
        if not m:
            return None
        class_name = m.group(1)
        assert self.class_name_pattern.search(text[m.end():]) is None
        return class_name.replace('/', '.')

    def _get_methods(self, text: str, class_name: str) -> List[ArtJniMethod]:
        class_base_name = class_name[class_name.rfind('.') + 1:]
        methods = []
        for p in self.method_patterns:
            for m in p.finditer(text):
                assert class_base_name == m.group(1)
                methods.append(
                    ArtJniMethod(
                        class_name, m.group(2),
                        class_base_name + '_' + m.group(2)))
        for p in self.overload_method_patterns:
            for m in p.finditer(text):
                assert class_base_name == m.group(1)
                methods.append(
                    ArtJniMethod(
                        class_name, m.group(2),
                        class_base_name + '_' + m.group(3)))
        return methods

    def _check_methods(self, text: str, methods: List[ArtJniMethod]):
        static_function_names = set()
        for m in self.static_function_pattern.finditer(text):
            static_function_names.add(m.group(1))
        for method in methods:
            assert method.native_method_name in static_function_names, (
                "%s isn't a static function in %s" % (method.native_method_name, self.file_path))


def collect_art_jni_methods() -> List[ArtJniMethod]:
    methods = []
    parser = ArtJniMethodParser()
    for file_path in ART_NATIVE_METHOD_DIR.iterdir():
        methods += parser.parse_methods(file_path)
    return methods


def art_jni_methods_to_str(methods: List[ArtJniMethod]):
    lines = ['// This file is generated by generate_art_jni_method_table.py.',
             '// clang-format off']
    for method in methods:
        lines.append(
            'ART_JNI_METHOD("%s", "%s")' %
            (method.class_name + '.' + method.java_method_name,
             "art::" + method.native_method_name))
    return '\n'.join(lines)


def main() -> bool:
    args = get_args()
    methods = collect_art_jni_methods()
    text = art_jni_methods_to_str(methods)
    if args.check_only:
        if text != OUTPUT_FILE.read_text():
            print('ART native methods have changed')
            return False
        return True
    OUTPUT_FILE.write_text(text)
    return True


if __name__ == '__main__':
    sys.exit(0 if main() else 1)
