#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Utility for generating changelogs for fix versions
# requirements: pip install jira
# Set $JIRA_USERNAME, $JIRA_PASSWORD environment variables

from __future__ import print_function

from collections import defaultdict
from datetime import datetime
from io import StringIO
import locale
import os
import sys

import jira.client

# ASF JIRA username
JIRA_USERNAME = os.environ.get("JIRA_USERNAME")
# ASF JIRA password
JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD")

JIRA_API_BASE = "https://issues.apache.org/jira"

asf_jira = jira.client.JIRA({'server': JIRA_API_BASE},
                            basic_auth=(JIRA_USERNAME, JIRA_PASSWORD))


locale.setlocale(locale.LC_ALL, 'en_US.utf-8')


def get_issues_for_version(version):
    jql = ("project=ARROW "
           "AND fixVersion='{0}' "
           "AND status = Resolved "
           "AND resolution in (Fixed, Done) "
           "ORDER BY issuetype DESC").format(version)

    return asf_jira.search_issues(jql, maxResults=9999)


LINK_TEMPLATE = '[{0}](https://issues.apache.org/jira/browse/{0})'


def format_changelog_markdown(issues, out):
    issues_by_type = defaultdict(list)
    for issue in issues:
        issues_by_type[issue.fields.issuetype.name].append(issue)

    for issue_type, issue_group in sorted(issues_by_type.items()):
        issue_group.sort(key=lambda x: x.key)

        out.write('## {0}\n\n'.format(_escape_for_markdown(issue_type)))
        for issue in issue_group:
            markdown_summary = _escape_for_markdown(issue.fields.summary)
            out.write('* {0} - {1}\n'.format(issue.key,
                                             markdown_summary))
        out.write('\n')


def _escape_for_markdown(x):
    return (
        x.replace('_', r'\_')  # underscores
        .replace('`', r'\`')   # backticks
        .replace('*', r'\*')   # asterisks
    )


def format_changelog_website(issues, out):
    NEW_FEATURE = 'New Features and Improvements'
    BUGFIX = 'Bug Fixes'

    CATEGORIES = {
        'New Feature': NEW_FEATURE,
        'Improvement': NEW_FEATURE,
        'Wish': NEW_FEATURE,
        'Task': NEW_FEATURE,
        'Test': BUGFIX,
        'Bug': BUGFIX,
        'Sub-task': NEW_FEATURE
    }

    issues_by_category = defaultdict(list)
    for issue in issues:
        issue_type = issue.fields.issuetype.name
        website_category = CATEGORIES[issue_type]
        issues_by_category[website_category].append(issue)

    WEBSITE_ORDER = [NEW_FEATURE, BUGFIX]

    for issue_category in WEBSITE_ORDER:
        issue_group = issues_by_category[issue_category]
        issue_group.sort(key=lambda x: x.key)

        out.write('## {0}\n\n'.format(issue_category))
        for issue in issue_group:
            name = LINK_TEMPLATE.format(issue.key)
            markdown_summary = _escape_for_markdown(issue.fields.summary)
            out.write('* {0} - {1}\n'
                      .format(name, markdown_summary))
        out.write('\n')


def get_changelog(version, for_website=False):
    issues_for_version = get_issues_for_version(version)

    buf = StringIO()

    if for_website:
        format_changelog_website(issues_for_version, buf)
    else:
        format_changelog_markdown(issues_for_version, buf)

    return buf.getvalue()


def append_changelog(version, changelog_path):
    new_changelog = get_changelog(version)

    with open(changelog_path, 'r') as f:
        old_changelog = f.readlines()

    result = StringIO()
    # Header
    print(''.join(old_changelog[:18]), file=result)

    # New version
    today = datetime.today().strftime('%d %B %Y')
    print('# Apache Arrow {0} ({1})'.format(version, today),
          end='', file=result)
    print('\n', file=result)
    print(new_changelog, end='', file=result)

    # Prior versions
    print(''.join(old_changelog[19:]), file=result)

    with open(changelog_path, 'w') as f:
        f.write(result.getvalue().rstrip() + '\n')


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Usage: changelog.py $FIX_VERSION [$IS_WEBSITE] '
              '[$CHANGELOG_TO_UPDATE]')

    for_website = len(sys.argv) > 2 and sys.argv[2] == '1'

    version = sys.argv[1]
    if len(sys.argv) > 3:
        changelog_path = sys.argv[3]
        append_changelog(version, changelog_path)
    else:
        print(get_changelog(version, for_website=for_website))
