# Copyright (c) 2011, Apple Inc. All rights reserved.
# Copyright (c) 2009, 2011, 2012 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# WebKit's Python module for committer and reviewer validation.

import fnmatch
import json
import sys

from functools import reduce
from webkitpy.common.editdistance import edit_distance
from webkitpy.common.memoized import memoized
from webkitpy.common.system.filesystem import FileSystem
from webkitpy.common.unicode_compatibility import encode_for, unicode


class Contributor(object):
    def __init__(self, name, email_or_emails, irc_nickname_or_nicknames=None, alias_or_aliases=None, expertise=None):
        assert(name)
        assert(email_or_emails)
        self.full_name = name
        if isinstance(email_or_emails, str):
            self.emails = [email_or_emails]
        else:
            self.emails = email_or_emails
        self._case_preserved_emails = self.emails
        self.emails = list(map(lambda email: email.lower(), self.emails))  # Emails are case-insensitive.

        if isinstance(irc_nickname_or_nicknames, str):
            self.irc_nicknames = [irc_nickname_or_nicknames]
        else:
            self.irc_nicknames = irc_nickname_or_nicknames

        if isinstance(alias_or_aliases, str):
            self.aliases = [alias_or_aliases]
        else:
            self.aliases = alias_or_aliases

        self.expertise = expertise
        self.can_commit = False
        self.can_review = False
        self.is_bot = False

    def bugzilla_email(self):
        # FIXME: We're assuming the first email is a valid bugzilla email,
        # which might not be right.
        return self.emails[0]

    def __str__(self):
        return encode_for(u'"{}" <{}>'.format(unicode(self.full_name), unicode(self.emails[0])), str)

    def __unicode__(self):
        return u'"{}" <{}>'.format(unicode(self.full_name), unicode(self.emails[0]))

    def __hash__(self):
        return hash(self.full_name) \
            ^ reduce(lambda a, b: hash(a) ^ hash(b), (self.emails or []) + [0]) \
            ^ reduce(lambda a, b: hash(a) ^ hash(b), (self._case_preserved_emails or []) + [0]) \
            ^ reduce(lambda a, b: hash(a) ^ hash(b), (self.irc_nicknames or []) + [0]) \
            ^ hash(self.expertise) \
            ^ hash(self.can_commit) \
            ^ hash(self.can_review)

    def __eq__(self, other):
        return (other is not None
            and self.full_name == other.full_name
            and self.emails == other.emails
            and self._case_preserved_emails == other._case_preserved_emails
            and self.irc_nicknames == other.irc_nicknames
            and self.expertise == other.expertise
            and self.can_commit == other.can_commit
            and self.can_review == other.can_review)

    def contains_string(self, search_string):
        string = search_string.lower()
        if string in self.full_name.lower():
            return True
        if self.irc_nicknames:
            for nickname in self.irc_nicknames:
                if string in nickname.lower():
                    return True
        if self.aliases:
            for alias in self.aliases:
                if string in alias.lower():
                    return True
        for email in self.emails:
            if string in email:
                return True
        return False

    def mentioned_in_text(self, text):
        lower_text = text.lower()
        if self.full_name.lower() in lower_text:
            return True
        if self.irc_nicknames:
            for nickname in self.irc_nicknames:
                if nickname.lower() in lower_text:
                    return True
        if self.aliases:
            for alias in self.aliases:
                if alias.lower() in lower_text:
                    return True
        for email in self.emails:
            if email in lower_text:
                return True
        return False

    def matches_glob(self, glob_string):
        if fnmatch.fnmatch(self.full_name, glob_string):
            return True
        if self.irc_nicknames:
            for nickname in self.irc_nicknames:
                if fnmatch.fnmatch(nickname, glob_string):
                    return True
        for email in self.emails:
            if fnmatch.fnmatch(email, glob_string):
                return True
        return False

    def as_dict(self):
        info = {"emails" : self._case_preserved_emails}

        if self.aliases:
            info["aliases"] = self.aliases

        if self.can_review:
            info["status"] = "reviewer"
        elif self.can_commit:
            info["status"] = "committer"

        if self.irc_nicknames:
            info["nicks"] = self.irc_nicknames

        if self.expertise:
            info["expertise"] = self.expertise

        if self.is_bot:
            info["class"] = "bot"

        return info


class Committer(Contributor):
    def __init__(self, name, email_or_emails, irc_nickname=None, alias_or_aliases=None, expertise=None):
        Contributor.__init__(self, name, email_or_emails, irc_nickname, alias_or_aliases, expertise)
        self.can_commit = True


class Reviewer(Committer):
    def __init__(self, name, email_or_emails, irc_nickname=None, alias_or_aliases=None, expertise=None):
        Committer.__init__(self, name, email_or_emails, irc_nickname, alias_or_aliases, expertise)
        self.can_review = True


class Bot(Contributor):
    def __init__(self, name, email_or_emails, irc_nickname=None, alias_or_aliases=None, expertise=None):
        Contributor.__init__(self, name, email_or_emails, irc_nickname, alias_or_aliases, expertise)
        self.is_bot = True


class CommitterList(object):

    # Committers and reviewers are passed in to allow easy testing
    def __init__(self,
                 committers=[],
                 reviewers=[],
                 contributors=[]):
        if committers or reviewers or contributors:
            self.load_test_data(committers, reviewers, contributors)
        else:
            self.load_json()

        self._contributors_by_name = {}
        self._accounts_by_email = {}
        self._accounts_by_login = {}

    def load_json(self):
        filesystem = FileSystem()
        json_path = filesystem.join(filesystem.dirname(filesystem.path_to_module('webkitpy.common.config')), 'contributors.json')
        try:
            contributors = json.loads(filesystem.read_text_file(json_path))
        except ValueError as e:
            sys.exit('contributors.json is malformed: ' + str(e))

        self._contributors = []
        self._committers = []
        self._reviewers = []

        for name, data in contributors.items():
            contributor = None
            status = data.get('status')
            if status == "reviewer":
                contributor = Reviewer(name, data.get('emails'), data.get('nicks'), data.get('aliases'), data.get('expertise'))
                self._reviewers.append(contributor)
                self._committers.append(contributor)
            elif status == "committer":
                contributor = Committer(name, data.get('emails'), data.get('nicks'), data.get('aliases'), data.get('expertise'))
                self._committers.append(contributor)
            elif data.get('class') == 'bot':
                contributor = Bot(name, data.get('emails'), data.get('nicks'), data.get('aliases'), data.get('expertise'))
            else:
                contributor = Contributor(name, data.get('emails'), data.get('nicks'), data.get('aliases'), data.get('expertise'))

            self._contributors.append(contributor)

    def load_test_data(self, committers, reviewers, contributors):
        self._contributors = contributors + committers + reviewers
        self._committers = committers + reviewers
        self._reviewers = reviewers

    @staticmethod
    def _contributor_list_to_dict(list):
        committers_dict = {}
        for contributor in sorted(list):
            committers_dict[contributor.full_name] = contributor.as_dict()
        return committers_dict

    def as_json(self):
        result = CommitterList._contributor_list_to_dict(self._contributors)
        return json.dumps(result, sort_keys=True, indent=3, separators=(',', ' : '))

    def reformat_in_place(self):
        filesystem = FileSystem()
        json_path = filesystem.join(filesystem.dirname(filesystem.path_to_module('webkitpy.common.config')), 'contributors.json')
        filesystem.write_text_file(json_path, self.as_json())

    # Contributors who are not in any other category.
    def _exclusive_contributors(self):
        return list(filter(lambda contributor: not (contributor.can_commit or contributor.can_review), self._contributors))

    # Committers who are not reviewers.
    def _exclusive_committers(self):
        return list(filter(lambda contributor: contributor.can_commit and not contributor.can_review, self._committers))

    # This is the superset of contributors + committers + reviewers
    def contributors(self):
        return self._contributors

    # This is the superset of committers + reviewers
    def committers(self):
        return self._committers

    def reviewers(self):
        return self._reviewers

    def _name_to_contributor_map(self):
        if not len(self._contributors_by_name):
            for contributor in self._contributors:
                assert contributor.full_name
                assert contributor.full_name.lower() not in self._contributors_by_name  # We should never have duplicate names.
                self._contributors_by_name[contributor.full_name.lower()] = contributor
                if contributor.aliases is None:
                    continue
                for alias in contributor.aliases:
                    assert alias.lower() not in self._contributors_by_name
                    self._contributors_by_name[alias.lower()] = contributor
        return self._contributors_by_name

    def _email_to_account_map(self):
        if not len(self._accounts_by_email):
            for account in self._contributors:
                for email in account.emails:
                    assert(email not in self._accounts_by_email)  # We should never have duplicate emails.
                    self._accounts_by_email[email] = account
        return self._accounts_by_email

    def _login_to_account_map(self):
        if not len(self._accounts_by_login):
            for account in self._contributors:
                if account.emails:
                    login = account.bugzilla_email()
                    assert(login not in self._accounts_by_login)  # We should never have duplicate emails.
                    self._accounts_by_login[login] = account
        return self._accounts_by_login

    def _committer_only(self, record):
        if record and not record.can_commit:
            return None
        return record

    def _reviewer_only(self, record):
        if record and not record.can_review:
            return None
        return record

    def contributor_by_irc_nickname(self, irc_nickname):
        for contributor in self.contributors():
            # FIXME: This should do case-insensitive comparison or assert that all IRC nicknames are in lowercase
            if contributor.irc_nicknames and irc_nickname in contributor.irc_nicknames:
                return contributor
        return None

    def contributors_by_search_string(self, string):
        glob_matches = list(filter(lambda contributor: contributor.matches_glob(string), self.contributors()))
        return glob_matches or list(filter(lambda contributor: contributor.contains_string(string), self.contributors()))

    def contributors_by_email_username(self, string):
        string = string + '@'
        result = []
        for contributor in self.contributors():
            for email in contributor.emails:
                if email.startswith(string):
                    result.append(contributor)
                    break
        return result

    def _contributor_name_shorthands(self, contributor):
        if ' ' not in contributor.full_name:
            return []
        split_fullname = contributor.full_name.split()
        first_name = split_fullname[0]
        last_name = split_fullname[-1]
        return first_name, last_name, first_name + last_name[0], first_name + ' ' + last_name[0]

    def _tokenize_contributor_name(self, contributor):
        full_name_in_lowercase = contributor.full_name.lower()
        tokens = [full_name_in_lowercase] + full_name_in_lowercase.split()
        if contributor.irc_nicknames:
            return tokens + [nickname.lower() for nickname in contributor.irc_nicknames if len(nickname) > 5]
        return tokens

    def contributors_by_fuzzy_match(self, string):
        string_in_lowercase = string.lower()

        # 1. Exact match for fullname, email and irc_nicknames
        account = self.contributor_by_name(string_in_lowercase) or self.contributor_by_email(string_in_lowercase) or self.contributor_by_irc_nickname(string_in_lowercase)
        if account:
            return [account], 0

        # 2. Exact match for email username (before @)
        accounts = self.contributors_by_email_username(string_in_lowercase)
        if accounts and len(accounts) == 1:
            return accounts, 0

        # 3. Exact match for first name, last name, and first name + initial combinations such as "Dan B" and "Tim H"
        accounts = [contributor for contributor in self.contributors() if string in self._contributor_name_shorthands(contributor)]
        if accounts and len(accounts) == 1:
            return accounts, 0

        # 4. Finally, fuzzy-match using edit-distance
        string = string_in_lowercase
        contributorWithMinDistance = []
        minDistance = len(string) / 2 - 1
        for contributor in self.contributors():
            tokens = self._tokenize_contributor_name(contributor)
            editdistances = [edit_distance(token, string) for token in tokens if abs(len(token) - len(string)) <= minDistance]
            if not editdistances:
                continue
            distance = min(editdistances)
            if distance == minDistance:
                contributorWithMinDistance.append(contributor)
            elif distance < minDistance:
                contributorWithMinDistance = [contributor]
                minDistance = distance
        if not len(contributorWithMinDistance):
            return [], len(string)
        return contributorWithMinDistance, minDistance

    def contributor_by_email(self, email):
        return self._email_to_account_map().get(email.lower()) if email else None

    def contributor_by_name(self, name):
        return self._name_to_contributor_map().get(name.lower()) if name else None

    def committer_by_email(self, email):
        return self._committer_only(self.contributor_by_email(email))

    def committer_by_name(self, name):
        return self._committer_only(self.contributor_by_name(name))

    def reviewer_by_email(self, email):
        return self._reviewer_only(self.contributor_by_email(email))

    def reviewer_by_name(self, email):
        return self._reviewer_only(self.contributor_by_name(email))
