"""
Checks the entries and tries to detect additional developer content, by retrieving websites or logging information from
stored Git repositories.
"""
# TODO bag of words (split, strip, lowercase) on dev names and try to detect sex and nationality
# TODO name is not unique (not even on GH) so maybe add name to profile name
# TODO for duplicate names, create ignore list
# TODO split devs with multiple gh or sf accounts (unlikely), start with most (like name Adam) - naming convention @01 etc.
# TODO check for devs without contact after gitlab/bitbucket/..
# TODO gitlab/bitbucket import
# TODO wikipedia search for all with more than 3 games

import time
from utils import osg, osg_ui


class DevelopersMaintainer:

    def __init__(self):
        self.developers = None
        self.entries = None

    def read_developer(self):
        self.developers = osg.read_developers()
        print('{} developers read'.format(len(self.developers)))

    def write_developer(self):
        if not self.developers:
            print('developers not yet loaded')
            return
        osg.write_developers(self.developers)
        print('{} developers written'.format(len(self.developers)))

    def check_for_duplicates(self):
        if not self.developers:
            print('developers not yet loaded')
            return
        start_time = time.process_time()
        developer_names = list(self.developers.keys())
        for index, name in enumerate(developer_names):
            for other_name in developer_names[index + 1:]:
                if osg.name_similarity(str.casefold(name), str.casefold(other_name)) > 0.85:
                    print(' {} - {} is similar'.format(name, other_name))
        print('duplicates checked (took {:.1f}s)'.format(time.process_time()-start_time))

    def check_for_orphans(self):
        """
        List developers without games.
        """
        if not self.developers:
            print('developers not yet loaded')
            return
        for dev in self.developers.values():
            if not dev['Games']:
                print(' {} has no games'.format(dev['Name']))
        print('orphans checked')

    def remove_orphans(self):
        """
        Remove developers without games.
        """
        if not self.developers:
            print('developers not yet loaded')
            return
        self.developers = {k: v for k,v in self.developers.items() if v['Games']}
        print('orphans removed ({} devs left)'.format(len(self.developers)))
        
    def check_for_missing_developers_in_entries(self):
        if not self.developers:
            print('developer not yet loaded')
            return
        if not self.entries:
            print('entries not yet loaded')
            return
        for dev in self.developers.values():
            dev_name = dev['Name']
            for entry_name in dev['Games']:
                x = [x for x in self.entries if x['Title'] == entry_name]
                assert len(x) <= 1
                if not x:
                    print('Entry "{}" listed as game of developer "{}" but this entry does not exist'.format(entry_name, dev_name))
                else:
                    entry = x[0]
                    if 'Developer' not in entry or dev_name not in entry['Developer']:
                        print('Entry "{}" listed in developer "{}" but not listed in that entry'.format(entry_name, dev_name))
        print('missed developer checked')

    def update_developers_from_entries(self):
        if not self.developers:
            print('developer not yet loaded')
            return
        if not self.entries:
            print('entries not yet loaded')
            return
        # loop over all developers and delete all games
        for dev in self.developers.values():
            dev['Games'] = []
        # loop over all entries and add this game to all developers of this game
        for entry in self.entries:
            entry_name = entry['Title']
            entry_devs = entry.get('Developer', [])
            for entry_dev in entry_devs:
                entry_dev = entry_dev.value  # ignore a possible comment
                if entry_dev in self.developers:
                    self.developers[entry_dev]['Games'].append(entry_name)
                else:
                    # completely new developer
                    self.developers[entry_dev] = {'Name': entry_dev, 'Games': [entry_name]}
        print('developers updated')

    def read_entries(self):
        self.entries = osg.read_entries()
        print('{} entries read'.format(len(self.entries)))

    def special_ops(self):
        # need entries loaded
        if not self.entries:
            print('entries not yet loaded')
            return

        # remove all developer that are orphans
        remove = [k for k, v in self.developers.items() if not v['Games']]
        for k in remove:
            del self.developers[k]

        # # comments for developers
        # for entry in self.entries:
        #     for developer in entry.get('Developer', []):
        #         if developer.comment:
        #             print('{:<25} - {:<25} - {}'.format(entry['File'], developer.value, developer.comment))


if __name__ == "__main__":

    m = DevelopersMaintainer()

    actions = {
        'Read developers': m.read_developer,
        'Write developers': m.write_developer,
        'Check for duplicates': m.check_for_duplicates,
        'Check for orphans': m.check_for_orphans,
        'Remove orphans': m.remove_orphans,
        'Check for games in developers not listed': m.check_for_missing_developers_in_entries,
        'Update developers from entries': m.update_developers_from_entries,
        'Special': m.special_ops,
        'Read entries': m.read_entries
    }

    osg_ui.run_simple_button_app('Maintenance developer', actions)