# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A tool for updating IDL COM headers/TLB after updating IDL template.

This tool must be run from a Windows machine at the source root directory.

Example:
    python3 tools/win/update_idl.py
"""

import os
import platform
import subprocess

class IDLUpdateError(Exception):
    """Module exception class."""


class IDLUpdater:
    """A class to update IDL COM headers/TLB files based on config."""

    def __init__(self, idl_gn_target: str, target_cpu: str,
                 is_chrome_branded: bool):
        self.idl_gn_target = idl_gn_target
        self.target_cpu = target_cpu
        self.is_chrome_branded = str(is_chrome_branded).lower()
        self.output_dir = r'out\idl_update'

    def update(self) -> None:
        print('Updating', self.idl_gn_target, 'IDL files for', self.target_cpu,
              'CPU, chrome_branded:', self.is_chrome_branded, '...')
        self._make_output_dir()
        self._gen_gn_args()
        self._autoninja_and_update()

    def _make_output_dir(self) -> None:
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)

    def _gen_gn_args(self) -> None:
        # If the gn_args file already exists and has the desired values then
        # don't touch it - this avoids unnecessary and expensive gn gen
        # invocations.
        gn_args_path = os.path.join(self.output_dir, 'args.gn')
        contents = (f'target_cpu="{self.target_cpu}"\n'
                    f'is_chrome_branded={self.is_chrome_branded}\n'
                    f'is_debug=true\n'
                    f'blink_symbol_level=0\n'
                    f'v8_symbol_level=0\n').format()
        if os.path.exists(gn_args_path):
            with open(gn_args_path, 'rt', newline='') as f:
                new_contents = f.read()
                if new_contents == contents:
                    return

        # `subprocess` may interpret the complex config values passed via
        # `--args` differently than intended. Generate the default gn.args first
        # and then update it by writing directly.

        # gen args with default values.
        print('Generating', gn_args_path, 'with default values.')
        subprocess.run(['gn.bat', 'gen', self.output_dir], check=True)

        # Manually update args.gn
        print('Write', gn_args_path, 'with desired config.')
        with open(gn_args_path, 'wt', newline='') as f:
            f.write(contents)
        print('Done.')

    def _autoninja_and_update(self) -> None:
        print('Check if update is needed by building the target...')
        # Use -j 1 since otherwise the exact build output is not deterministic.
        proc = subprocess.run([
            'autoninja.bat', '-j', '1', '-C', self.output_dir,
            self.idl_gn_target
        ],
                              capture_output=True,
                              check=False,
                              universal_newlines=True)
        if proc.returncode == 0:
            print('No update is needed.\n')
            return

        cmd = self._extract_update_command(proc.stdout, proc.stderr)
        print('Updating IDL COM headers/TLB by running: [', cmd, ']...')
        subprocess.run(cmd, shell=True, capture_output=True, check=True)
        print('Done.\n')

    def _extract_update_command(self, stdout: str, stderr: str) -> str:
        # Exclude blank lines.
        lines = list(filter(None, stdout.splitlines()))

        if (len(lines) < 3 or 'build stopped' not in lines[-1]
                or 'copy /y' not in lines[-2]
                or 'To rebaseline:' not in lines[-3]):
            print('-' * 80)
            print('STDOUT:')
            print(stdout)
            print('-' * 80)
            print('STDERR:')
            print(stderr)
            print('-' * 80)
            print('LINE:')
            print(lines[-1])
            print(lines[-2])
            print(lines[-3])

            raise IDLUpdateError(
                'Unexpected autoninja error (see output above). Update this '
                'tool if the output format has changed.')

        return lines[-2].strip().replace('..\\..\\', '')


def check_running_environment() -> None:
    if 'Windows' not in platform.system():
        raise IDLUpdateError('This tool must run from Windows platform.')

    proc = subprocess.run(['git.bat', 'rev-parse', '--show-toplevel'],
                          capture_output=True,
                          check=True)

    if proc.returncode != 0:
        raise IDLUpdateError(
            'Failed to run git for finding source root directory.')

    source_root = os.path.abspath(proc.stdout.decode('utf-8').strip()).lower()
    if not os.path.exists(source_root):
        raise IDLUpdateError('Unexpected failure to get source root directory')

    cwd = os.getcwd().lower()
    if cwd != source_root:
        raise IDLUpdateError(f'This tool must run from project root folder. '
                             f'CWD: [{cwd}] vs ACTUAL:[{source_root}]')

    # Build performance output interferes with error parsing. Silence it.
    os.environ['NINJA_SUMMARIZE_BUILD'] = '0'


def main():
    check_running_environment()

    for target_cpu in ['arm64', 'x64', 'x86']:
        for idl_target in [
                'chrome/windows_services/elevated_tracing_service:' + \
                'tracing_service_idl',
                'chrome/windows_services/service_program:test_service_idl',
                'elevation_service_idl',
                'gaia_credential_provider_idl',
                'iaccessible2',
                'ichromeaccessible',
                'isimpledom',
                'remoting_lib_idl',
                'updater_idl',
                'updater_idl_system',
                'updater_idl_user',
                'updater_internal_idl',
                'updater_internal_idl_system',
                'updater_internal_idl_user',
                'updater_legacy_idl',
                'updater_legacy_idl_system',
                'updater_legacy_idl_user',
        ]:
            IDLUpdater(idl_target + '_idl_action', target_cpu, False).update()


if __name__ == '__main__':
    main()
