#!/usr/bin/env python

import glob
import os
from pathlib import Path

class Copyright:
    NOTICE = """Licensed to the Software Freedom Conservancy (SFC) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The SFC licenses this file
to you 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."""

    def __init__(self, comment_characters='//', prefix=None):
        self._comment_characters = comment_characters
        self._prefix = prefix or []

    def update(self, files):
        for file in files:
            with open(file, 'r', encoding='utf-8-sig') as f:
                lines = f.readlines()

            index = -1
            for i, line in enumerate(lines):
                if line.startswith(self._comment_characters) or \
                  self.valid_copyright_notice_line(line, index, file):
                    index += 1
                else:
                    break

            if index == -1:
                self.write_update_notice(file, lines)
            else:
                current = ''.join(lines[:index + 1])
                if current != self.copyright_notice(file):
                    self.write_update_notice(file, lines[index + 1:])

    def valid_copyright_notice_line(self, line, index, file):
        return index + 1 < len(self.copyright_notice_lines(file)) and \
            line.startswith(self.copyright_notice_lines(file)[index + 1])

    def copyright_notice(self, file):
        return ''.join(self.copyright_notice_lines(file))

    def copyright_notice_lines(self, file):
        return self.dotnet(file) if file.endswith("cs") else self._prefix + self.commented_notice_lines

    def dotnet(self, file):
        file_name = os.path.basename(file)
        first = f"{self._comment_characters} <copyright file=\"{file_name}\" company=\"Selenium Committers\">\n"
        last = f"{self._comment_characters} </copyright>"
        return [first] + self.commented_notice_lines + [last]

    @property
    def commented_notice_lines(self):
        return [f"{self._comment_characters} {line}".rstrip() + "\n" for line in self.NOTICE.split('\n')]

    def write_update_notice(self, file, lines):
        print(f"Adding notice to {file}")
        with open(file, 'w') as f:
            f.write(self.copyright_notice(file) + "\n")
            if lines and lines[0] != "\n":
                f.write("\n")
            trimmed_lines = [line.rstrip() + "\n" for line in lines]
            f.writelines(trimmed_lines)

ROOT = Path(os.path.realpath(__file__)).parent.parent

JS_EXCLUSIONS = [
    f"{ROOT}/javascript/atoms/test/jquery.min.js",
    f"{ROOT}/javascript/jsunit/**/*.js",
    f"{ROOT}/javascript/node/selenium-webdriver/node_modules/**/*.js",
    f"{ROOT}/javascript/selenium-core/lib/**/*.js",
    f"{ROOT}/javascript/selenium-core/scripts/ui-element.js",
    f"{ROOT}/javascript/selenium-core/scripts/ui-map-sample.js",
    f"{ROOT}/javascript/selenium-core/scripts/user-extensions.js",
    f"{ROOT}/javascript/selenium-core/scripts/xmlextras.js",
    f"{ROOT}/javascript/selenium-core/xpath/**/*.js",
    f"{ROOT}/javascript/grid-ui/node_modules/**/*.js"
]

PY_EXCLUSIONS = [
    f"{ROOT}/py/selenium/webdriver/common/bidi/cdp.py",
    f"{ROOT}/py/generate.py",
    f"{ROOT}/py/selenium/webdriver/common/devtools/**/*",
    f"{ROOT}/py/venv/**/*"
]


def update_files(file_pattern, exclusions, comment_characters='//', prefix=None):
    included = set(glob.glob(file_pattern, recursive=True))
    excluded = set()
    for pattern in exclusions:
        excluded.update(glob.glob(pattern, recursive=True))
    files = included - excluded

    copyright = Copyright(comment_characters, prefix)
    copyright.update(files)


if __name__ == "__main__":
    update_files(f"{ROOT}/javascript/**/*.js", JS_EXCLUSIONS)
    update_files(f"{ROOT}/javascript/**/*.tsx", [])
    update_files(f"{ROOT}/py/**/*.py", PY_EXCLUSIONS, comment_characters="#")
    update_files(f"{ROOT}/rb/**/*.rb", [], comment_characters="#", prefix=["# frozen_string_literal: true\n", "\n"])
    update_files(f"{ROOT}/java/**/*.java", [])
    update_files(f"{ROOT}/rust/**/*.rs", [])
    update_files(f"{ROOT}/dotnet/**/*.cs", [])
