#!/usr/bin/python3.13

# Purple - Internet Messaging Library
# Copyright (C) Pidgin Developers <devel@pidgin.im>
#
# Purple is the legal property of its developers, whose names are too numerous
# to list here. Please refer to the COPYRIGHT file distributed with this
# source distribution.
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this library; if not, see <https://www.gnu.org/licenses/>.

import argparse
import json
import difflib
import os
import os.path
import sys

from pathlib import Path

parser = argparse.ArgumentParser(
    prog='birb-check-license-headers',
    description='checks that the license headers of source files match a template',
    epilog='This should probably only be ran by meson as a test')

parser.add_argument(
    '-d', '--debug',
    action=argparse.BooleanOptionalAction,
    help='show debug message')

parser.add_argument(
    'template',
    type=argparse.FileType('r'),
    help='the file containing the template header')

parser.add_argument(
    'sources',
    nargs='+',
    help='the source file names to check')

args = parser.parse_args()

if len(args.sources) == 0:
    print(f'no sources provided')
    sys.exit(1)

if args.debug:
    print(f'sources: {json.dumps(args.sources, indent=4)}')

header = args.template.read().splitlines(keepends=True)
if header[-1] != '\n':  # Always separate header from body with a blank line.
    header.append('\n')
header_lines = len(header)

error = False


for filename in args.sources:
    _, ext = os.path.splitext(filename)

    # We only want to check source files.
    if not ext in ['.c', '.cc', '.cpp', '.h', '.m']:
        continue

    file_data = None
    with open(filename, 'r', encoding='utf-8') as f:
        file_data = f.read().splitlines(keepends=True)

    # Look for a starting comment ignoring newlines, if we find code, abort.
    comment_start = False
    comment_end = 0
    for i, line in enumerate(file_data):
        if line.startswith('/*'):
            comment_start = True
        elif comment_start and line.endswith('*/\n'):
            comment_end = i
            continue

        if line.strip() == '':
            continue

        if comment_start and comment_end != 0:
            header_end = i
            break

    if comment_start:
        new_data = header + file_data[header_end:]
    else:
        new_data = header + file_data

    if args.debug:
        sys.stdout.writelines(new_data[:30])
        print(f'comment_start: {comment_start}')
        print(f'comment_end: {comment_end}')
        print(f'header_end: {header_end}')
        sys.stdout.writelines(file_data[:25])

    diff = [*difflib.unified_diff(file_data, new_data,
                                  fromfile=f'a/{filename}',
                                  tofile=f'b/{filename}')]
    if diff:
        sys.stdout.writelines(diff)
        error = True

    if args.debug:
        sys.exit(1)

if error:
    sys.exit(1)
