from changelog.git import stage_file
from changelog.util import load_all_released_changes, load_unreleased_changes, version_cmp
from functools import cmp_to_key
from operator import attrgetter

class ChangelogWriter(object):
    """
    Writes ReleaseChanges objects to a file using the following format:

    # __VERSION__ __YYYY-MM-DD__
    ## __Category__
      - ### __Features__
        - ...
      - ### __Bugfixes__
        - ...
      - ### __Deprecations__
        - ...
    """

    def __init__(self, output_file):
        self.output_file = output_file

    def write_changes(self, changes):
        self.process_changes(changes)
        self.write_header()
        for s in self.get_sorted_categories():
            self.write_category_header(s)
            self.write_items_for_category(s, self.features, "Features")
            self.write_items_for_category(s, self.bugfixes, "Bugfixes")
            self.write_items_for_category(s, self.deprecations, "Deprecations")
            self.write_items_for_category(s, self.removals, "Removals")
            self.write_items_for_category(s, self.documentations, "Documentations")
        self.write_contributors()

    def write_contributors(self):
        contributors = set()
        for e in self.current_changes.entries:
            if e.contributor:
                contributors.add(self.contributor_with_link(e.contributor))

        if contributors:
            self.output_file.write("## __Contributors__\n")
            contributors_string = ', '.join(contributors)
            self.output_file.write("Special thanks to the following contributors to this release: \n")
            self.output_file.write("\n" + contributors_string + "\n")

    def contributor_with_link(self, contributor):
        return "[@" + contributor + "]" + "(" + \
               "https://github.com/" + contributor + ")"

    def process_changes(self, changes):
        self.current_changes = changes
        self.reset_maps()
        self.group_entries()

    def reset_maps(self):
        self.features = {}
        self.bugfixes = {}
        self.deprecations = {}
        self.removals = {}
        self.documentations = {}
        self.categories = set()

    def group_entries(self):
        for e in self.current_changes.entries:
            m = self.get_map_for_type(e.type)
            m.setdefault(e.category, []).append(e)
            self.categories.add(e.category)

    def get_sorted_categories(self):
        return sorted(list(self.categories))

    def is_service_category(self,s):
        return s.lower() not in NON_SERVICE_CATEGORIES

    def write_header(self):
        version_string = self.current_changes.version
        if version_string is None:
            version_string = "@AWS_JAVA_SDK_VERSION@"
        self.write("# __%s__ __%s__\n" % (version_string, self.current_changes.date))

    def write_category_header(self, c):
        self.output_file.write("## __%s__\n" % c)

    def write_items_for_category(self, category, map, header):
        entries = map.get(category, [])
        items = sorted(entries, key=attrgetter('description'))
        self.write_entries_with_header(header, items)

    def write_entries_with_header(self, header, entries):
        if not len(entries) > 0:
            return
        self.write("  - ### %s\n" % header)
        for e in entries:
            self.write_entry(e)
        self.write('\n')

    def write_entry(self,e):
        description = e.description
        entry_lines = description.splitlines(True)
        self.write("    - %s" % entry_lines[0])
        for l in entry_lines[1:]:
            if len(l.strip()) == 0:
                self.write("\n")
            else:
                self.write("      %s" % l)
        self.write('\n')
        if e.contributor:
            self.write("        - ")
            self.write("Contributed by: " + self.contributor_with_link(e.contributor))
            self.write('\n')

    def get_map_for_type(self, t):
        if t == 'feature':
            return self.features
        elif t == 'bugfix':
            return self.bugfixes
        elif t == 'deprecation':
            return self.deprecations
        elif t == 'removal':
            return self.removals
        elif t == 'documentation':
            return self.documentations
        else:
            raise Exception("Unknown entry type %s!" % t)

    def write(self, s):
        self.output_file.write(s)

def write_archived_changelogs_message(changelog_file):
    message = " #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._\n"
    changelog_file.write(message)

def write_changelog():
    unreleased = load_unreleased_changes(".changes/next-release")
    released = load_all_released_changes(".changes")
    released = sorted(released, key=lambda c: [c.version.major, c.version.minor, c.version.patch, c.version.prerelease_version_number()], reverse=True)

    if unreleased is not None:
        all_changes = [unreleased] + released
    else:
        all_changes = released

    if len(all_changes) == 0:
        return

    with open('CHANGELOG.md', 'w') as cl:
        write_archived_changelogs_message(cl)
        writer = ChangelogWriter(cl)
        for changes in all_changes:
            writer.write_changes(changes)

    stage_file('CHANGELOG.md')
