#!/usr/bin/env python3
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tool to collect stats about progress of adding @NullMarked."""

import argparse
import collections
import csv
from datetime import date
import logging
import pathlib
import sys
import time

_SRC_ROOT = pathlib.Path(__file__).resolve().parents[3]

_EXCLUDED_SUBDIRS = ('out', 'third_party')
_TEST_PATH_SUBSTRINGS = ('test', 'Test')

_SUBDIRS_FOR_STATS = [
    'base',
    'chrome',
    'android_webview',
    'components',
    'content',
    'clank',
]


def _is_test(file):
    return any(s in str(file.absolute()) for s in _TEST_PATH_SUBSTRINGS)


def _collect_java_files(start_dir):
    path = pathlib.Path(start_dir)
    for file in path.glob('**/*.java'):
        file.resolve()
        if not file.is_file():
            continue
        # Ignore files in excluded subdirs.
        for excluded_subdir in _EXCLUDED_SUBDIRS:
            if (_SRC_ROOT / excluded_subdir) in file.parents:
                break
        else:
            yield file


def _check_if_marked(java_files):
    marked_all = set()
    unmarked_all = set()
    nomark_all = set()
    for path in java_files:
        data = path.read_text()
        marked = '@NullMarked' in data
        unmarked = '@NullUnmarked' in data
        if marked:
            marked_all.add(path)
        elif not unmarked:
            nomark_all.add(path)
        if unmarked:
            unmarked_all.add(path)

    return marked_all, nomark_all, unmarked_all


def _breadown_stats_by_subdir(files):
    ret = collections.defaultdict(int)
    for file in files:
        for subdir in _SUBDIRS_FOR_STATS:
            if (_SRC_ROOT / subdir) in file.parents:
                ret[subdir] += 1
    return ret


def _print_stats(marked_all, nomark_all, unmarked_all):
    marked_by_subdirs = _breadown_stats_by_subdir(marked_all)
    nomark_by_subdirs = _breadown_stats_by_subdir(nomark_all)
    unmarked_by_subdirs = _breadown_stats_by_subdir(unmarked_all)
    count_marked = len(marked_all)
    count_nomark = len(nomark_all)
    count_unmarked = len(unmarked_all)
    total = count_marked + count_nomark

    def stat(c, t):
        pct_string = str(round(c / t * 100)) if t != 0 else '-'
        return f'{c}/{t} ({pct_string}%)'

    print()
    print(f'Overall:')
    print(f'  @NullMarked:', stat(count_marked, total))
    print(f'  Neither:', stat(count_nomark, total))
    print(f'  @NullUnmarked:', stat(count_unmarked, total))
    print()
    print(f'By Directory (@NullMarked / Neither / @NullUnmarked):')
    for subdir in _SUBDIRS_FOR_STATS:
        subdir_marked_count = marked_by_subdirs[subdir]
        subdir_nomark_count = nomark_by_subdirs[subdir]
        subdir_unmarked_count = unmarked_by_subdirs[subdir]
        subdir_total = subdir_marked_count + subdir_nomark_count
        # Skip non-existent subdirs.
        if subdir_total == 0:
            continue
        print(
            f'  //{subdir}:',
            stat(subdir_marked_count, subdir_total),
            '/',
            stat(subdir_nomark_count, subdir_total),
            '/',
            stat(subdir_unmarked_count, subdir_total),
        )


def _read_file_list(filepath):
    with open(filepath, 'rt') as f:
        return (pathlib.Path(java_file.strip()) for java_file in f.readlines())


def _write_file_list(filepath, filelist):
    sorted_filelist = sorted(filelist)
    with open(filepath, 'wt') as f:
        f.writelines(f'{str(p)}\n' for p in sorted_filelist)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        '-C', dest='src_dir', default=_SRC_ROOT, help='Path to CHROMIUM_SRC.'
    )
    parser.add_argument(
        '--unmarked-list-path',
        help='Path to output the list of files with @NullUnmarked.',
    )
    parser.add_argument(
        '--marked-list-path',
        help='Path to output the list of files with @NullMarked.',
    )
    parser.add_argument(
        '--nomark-list-path',
        help='Path to output the list of files without any annotation.',
    )
    parser.add_argument(
        '--cached-file-list',
        help='Path to list of java files instead of walking the tree.',
    )
    parser.add_argument(
        '--output-file-list',
        help='Path to output list of java files for use by --cached-file-list.',
    )
    parser.add_argument('--csv', action='store_true', help='Output a .csv')
    parser.add_argument('-v', '--verbose', action='store_true')
    options = parser.parse_args(sys.argv[1:])

    logging_level = logging.INFO
    if options.verbose:
        logging_level = logging.DEBUG
    logging.basicConfig(level=logging_level)

    if options.cached_file_list and options.output_file_list:
        parser.error(
            'Cant pass in both --cached-file-list and --output-file-list'
        )

    logging.info('Collecting java files')
    start = time.time()
    if options.cached_file_list:
        java_files = _read_file_list(options.cached_file_list)
    else:
        java_files = list(_collect_java_files(options.src_dir))
    logging.info(f'Collecting java files done in {time.time() - start:.1f}s')

    logging.info('Processing files')
    start = time.time()
    marked, nomark, unmarked = _check_if_marked(java_files)
    logging.info(f'Processing files files done in {time.time() - start:.1f}s')

    if options.unmarked_list_path:
        _write_file_list(options.unmarked_list_path, unmarked)
    if options.marked_list_path:
        _write_file_list(options.marked_list_path, marked)
    if options.nomark_list_path:
        _write_file_list(options.nomark_list_path, nomark)
    if options.output_file_list:
        _write_file_list(options.output_file_list, java_files)

    logging.info('Calculating stats')
    start = time.time()
    marked_tests = {x for x in marked if _is_test(x)}
    marked.difference_update(marked_tests)
    nomark_tests = {x for x in nomark if _is_test(x)}
    nomark.difference_update(nomark_tests)
    unmarked_tests = {x for x in unmarked if _is_test(x)}
    unmarked.difference_update(unmarked_tests)

    if options.csv:
        csv.writer(sys.stdout).writerow(
            (
                date.today(),
                len(marked),
                len(nomark),
                len(unmarked),
                len(marked_tests),
                len(nomark_tests),
                len(unmarked_tests),
            )
        )
    else:
        print(date.today())
        print('==== Non-test Files ====')
        _print_stats(marked, nomark, unmarked)
        print()
        print('====== Test Files ======')
        _print_stats(marked_tests, nomark_tests, unmarked_tests)
    logging.info(f'Calculating stats done in {time.time() - start:.1f}s')


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