# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# SPDX-License-Identifier: GPL-2.0-or-later

import os
import re
import subprocess

# For text colouring/highlighting.
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    ADDED = '\033[45m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

# TODO: include signal_handler() + should_exit, but didn't work (problem with should_exit?)

def isDissectorFile(filename):
    if not filename.endswith('.c'):
        return False

    abs_path = os.path.abspath(filename)
    if os.path.join('plugins', 'epan') in abs_path:
        return True
    elif os.path.join('epan', 'dissectors') in abs_path:
        p = re.compile(r'.*(packet|file)-.*\.c$')
        return p.match(filename)
    else:
        return False


# Test for whether the given file was automatically generated.
def isGeneratedFile(filename):
    # Check file exists - e.g. may have been deleted in a recent commit.
    if not os.path.exists(filename):
        return False

    # Open file
    f_read = open(os.path.join(filename), 'r', encoding="utf8", errors="ignore")
    lines_tested = 0
    for line in f_read:
        # The comment to say that its generated is near the top, so give up once
        # get a few lines down.
        if lines_tested > 10:
            f_read.close()
            return False
        if ('Generated automatically' in line or
            'Generated Automatically' in line or
            'Autogenerated from' in line or
            'is autogenerated' in line or
            'automatically generated by Pidl' in line or
            'Created by: The Qt Meta Object Compiler' in line or
            'This file was generated' in line or
            'This filter was automatically generated' in line or
            'This file is auto generated' in line or
            'this file is automatically generated' in line):

            f_read.close()
            return True
        lines_tested = lines_tested + 1

    # OK, looks like a hand-written file!
    f_read.close()
    return False

def removeComments(code_string):
    # C-style comment
    code_string = re.sub(re.compile(r"(?<!/)/\*.*?\*/", re.DOTALL), "" , code_string)
    # C++-style comment
    # Avoid matching // where it is allowed, e.g.,  https://www... or file:///...
    code_string = re.sub(re.compile(r"(?<!:)(?<!/)(?<!\")(?<!\"\s\s)(?<!file:/)(?<!\.)(?<!\,\s)(?<!\\n)//.*?\n" ),
                         "" , code_string)
    code_string = re.sub(re.compile(r"#if 0.*?#endif",re.DOTALL ) ,"" , code_string) # Ignored region

    return code_string

def findDissectorFilesInFolder(folder, recursive=False, include_generated=True):
    dissector_files = []

    if recursive:
        for root, subfolders, files in os.walk(folder):
            for f in files:
                f = os.path.join(root, f)
                dissector_files.append(f)
    else:
        for f in sorted(os.listdir(folder)):
            filename = os.path.join(folder, f)
            dissector_files.append(filename)

    return [x for x in dissector_files if (isDissectorFile(x) and (include_generated or not isGeneratedFile(x)))]

def getFilesFromCommits(commits, onlyDissectors=True):
    # Get files affected by specified number of commits.
    command = ['git', 'diff', '--name-only', '--diff-filter=d', 'HEAD~' + commits]
    files = [f.decode('utf-8')
             for f in subprocess.check_output(command).splitlines()]
    # Only interested in dissector files?
    if onlyDissectors:
        files = list(filter(lambda f : isDissectorFile(f), files))
    return files

def getFilesFromOpen(onlyDissectors=True):
    command = ['git', 'diff', '--name-only', '--diff-filter=d']
    files = [f.decode('utf-8')
             for f in subprocess.check_output(command).splitlines()]
    files = list(filter(lambda f : isDissectorFile(f), files))
    # Staged changes.
    command = ['git', 'diff', '--staged', '--name-only', '--diff-filter=d']
    files_staged = [f.decode('utf-8')
                    for f in subprocess.check_output(command).splitlines()]
    # Only interested in dissector files.
    files_staged = list(filter(lambda f : isDissectorFile(f), files_staged))
    for f in files_staged:
        if f not in files:
            files.append(f)

    # Only interested in dissector files?
    if onlyDissectors:
        files = list(filter(lambda f : isDissectorFile(f), files))
    return files

