import re
from bs4 import BeautifulSoup
import csv

with open('myfile1.txt', 'r') as f:
    # Reading through each changeset
    for line in f:
        line = line.strip()
        with open(line + '.html', 'r') as f:
            r = f.read()
            soup = BeautifulSoup(r, 'html.parser')

            csv_file = open("data.csv", "a")
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow(["Bugs", "ChangeSet", "PushDate", "Files", "Added Lines", "Deleted Lines", "Changed Functions"])

            # Defining the list
            bug_id = []
            hash_set = []
            push_date = []
            function = []
            add_lines = []
            delete_lines = []
            alter_files = []

            # Finding the associated bug id
            bug = soup.find('div', class_='title_text').find_all('td')[-1]
            bugs = bug.text
            # print(bugs)
            bug_id.append(bugs)
            _bug = " 'NextBug' ".join(bug_id)

            # Finding the change set
            change_set = soup.find('a', class_='list')
            hash_set = change_set.text
            # print(hash_set)

            # Finding the push date
            date = soup.find('td', class_='date age')
            push_date = date.text
            # print(push_date)

            # Name of the altered files
            for item in soup.find_all('a', class_='list')[3:]:
                files = item.text.split('/')[-1]
                # print(files)
                alter_files.append(files)
                file = " 'NextFile' ".join(alter_files)

            # Code to get the added lines and their respective functions
            count = 0

            # Looping through all the added lines
            for lines in soup.find_all('span', class_="difflineplus"):
                if '+  ' in lines.text:
                    add = lines.text

                    # Finding the previous sibling with <span> tag
                    for sib in lines.find_previous_siblings('span'):
                        lists = sib.text.strip()

                        try:
                            # Regular expressions for fetching the functions/methods
                            if re.search(r'.*function.*\(.*\)*\s*\{*', lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'(bool|char|int|float|double|void|wchar_t).*\(.*\)\s*.*\{*', lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'.*(bool|char|int|float|double|void|wchar_t).*\::', lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(
                                    r'(public|private|static|protected|abstract|native|synchronized)\s*(void)*.*\(.*\)\s*\{*',
                                    lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'.*(public|private|static|protected|abstract|native|synchronized).*\::',
                                           lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'\s*def.*\(.*\):', lists) is not None:
                                if count < 1:
                                    # print(add)
                                    add_lines.append(add)
                                    _add = " 'NextAddedLine' ".join(add_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                        except:
                            AttributeError
                    count = 0

            # Code to get the deleted lines and their respective functions
            count = 0
            for line in soup.find_all('span', class_="difflineminus"):
                if '-  ' in line.text:
                    delete = line.text
                    for sib in line.find_previous_siblings('span'):
                        lists = sib.text.strip()

                        try:
                            if re.search(r'.*function.*\(.*\)*\s*\{*', lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = " ' NextDeletedLine' ".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'(bool|char|int|float|double|void|wchar_t).*\(.*\)\s*.*\{*', lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = "NextDeletedLine".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'.*(bool|char|int|float|double|void|wchar_t).*\::', lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = " 'NextDeletedLine' ".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(
                                    r'(public|private|static|protected|abstract|native|synchronized)\s*(void)*.*\(.*\)\s*\{*',
                                    lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = " 'NextDeletedLine' ".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'.*(public|private|static|protected|abstract|native|synchronized).*\::',
                                           lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = " 'NextDeletedLine' ".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1
                            elif re.search(r'\s*def.*\(.*\):', lists) is not None:
                                if count < 1:
                                    # print(delete)
                                    delete_lines.append(delete)
                                    _delete = " 'NextDeletedLine' ".join(delete_lines)
                                    functions = lists.split('@@')[-1];
                                    # print(functions)
                                    function.append(functions)
                                    funct = " 'NextFunction' ".join(function)
                                    count += 1

                        except:
                            AttributeError
                    count = 0

            # Writing into csv file
            csv_writer.writerow([_bug, hash_set, push_date, file, _add, _delete, funct])
            csv_file.close()
