#!/usr/bin/env python
# This file is borrowed from the aws/aws-cli project with the following modifications:
#  - Add a 'deprecation' category, and validation for the category value
#  - Modify the 'linkify' method to use Markdown syntax instead of reStructuredText (rst)
#  - Better error reporting when one or more of the fields are empty
#  - Change filename format to use a the SHA1 digest of the content instead of a random number
#  - Change references to aws/cli to aws/aws-sdk-java
"""Generate a new changelog entry.

Usage
=====

To generate a new changelog entry::

    bin/new-change

This will open up a file in your editor (via the ``EDITOR`` env  var).
You'll see this template::
    # Type should be one of: feature, bugfix, deprecation, removal, documentation
    type: {change_type}

    # The marketing name of the service this change applies to
    # e.g: AWS CodeCommit, Amazon DynamoDB
    # or "AWS SDK for Java v2" if it's an SDK change to the core, runtime etc
    category: {category}


    The description of the change. Feel free to use Markdown here.
    description: {description}

Fill in the appropriate values, save and exit the editor.

If, when your editor is open, you decide don't don't want to add a changelog
entry, save an empty file and no entry will be generated.

"""
import argparse
import hashlib
import json
import os
import re
import string
import subprocess
import sys
import tempfile

from changelog.git import stage_file

VALID_CHARS = set(string.ascii_letters + string.digits)
CHANGES_DIR = os.path.join(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
    '.changes'
)
CHANGE_PARTS = ['type', 'category', 'description']
TEMPLATE = """\
# Type should be one of: feature, bugfix, deprecation, removal, documentation
type: {change_type}

# The marketing name of the service this change applies to
# e.g: AWS CodeCommit, Amazon DynamoDB
# or "AWS SDK for Java v2" if it's an SDK change to the core, runtime etc
category: {category}

# Your GitHub username (without '@') to be included in the CHANGELOG.
# Every contribution counts and we would like to recognize
# your contribution!
# Leave it empty if you would prefer not to be mentioned.
contributor: {contributor}

The description of the change. Feel free to use Markdown here.
description: {description}
"""


def new_changelog_entry(args):
    # Changelog values come from one of two places.
    # Either all values are provided on the command line,
    # or we open a text editor and let the user provide
    # enter their values.
    if all_values_provided(args):
        parsed_values = {
            'type': args.change_type,
            'category': args.category,
            'description': args.description,
            'contributor': args.contributor
        }
    else:
        parsed_values = get_values_from_editor(args)
        missing_parts = get_missing_parts(parsed_values)
        if len(missing_parts) > 0:
            sys.stderr.write(
                "No values provided for: %s. Skipping entry creation.\n" % missing_parts)
            return 1

    replace_issue_references(parsed_values, args.repo)
    filename = write_new_change(parsed_values)
    return stage_file(filename)

def get_missing_parts(parsed_values):
    return [p for p in CHANGE_PARTS if not parsed_values.get(p)]


def all_values_provided(args):
    return args.change_type and args.category and args.description and args.contributor


def get_values_from_editor(args):
    with tempfile.NamedTemporaryFile('w') as f:
        contents = TEMPLATE.format(
            change_type=args.change_type,
            category=args.category,
            description=args.description,
            contributor=args.contributor
        )
        f.write(contents)
        f.flush()
        env = os.environ
        editor = env.get('VISUAL', env.get('EDITOR', 'vim'))
        p = subprocess.Popen('%s %s' % (editor, f.name), shell=True)
        p.communicate()
        with open(f.name) as f:
            filled_in_contents = f.read()
            parsed_values = parse_filled_in_contents(filled_in_contents)
            return parsed_values


def replace_issue_references(parsed, repo_name):
    description = parsed['description']

    def linkify(match):
        number = match.group()[1:]
        return (
            '[%s](https://github.com/%s/issues/%s)' % (
                match.group(), repo_name, number))

    new_description = re.sub('(?<!\[)#\d+', linkify, description)
    parsed['description'] = new_description

def write_new_change(parsed_values):
    if not os.path.isdir(CHANGES_DIR):
        os.makedirs(CHANGES_DIR)
    # Assume that new changes go into the next release.
    dirname = os.path.join(CHANGES_DIR, 'next-release')
    if not os.path.isdir(dirname):
        os.makedirs(dirname)
    # Need to generate a unique filename for this change.
    category = parsed_values['category']

    contributor = parsed_values['contributor']
    if contributor and contributor.strip:
        contributor = remove_prefix(contributor, '@')
        parsed_values['contributor'] = contributor

    short_summary = ''.join(filter(lambda x: x in VALID_CHARS, category))
    contents = json.dumps(parsed_values, indent=4) + "\n"
    contents_digest = hashlib.sha1(contents.encode('utf-8')).hexdigest()
    filename = '{type_name}-{summary}-{digest}.json'.format(
        type_name=parsed_values['type'],
        summary=short_summary,
        digest=contents_digest[0:7])
    filename = os.path.join(dirname, filename)
    with open(filename, 'w') as f:
        f.write(contents)
    return filename

def remove_prefix(text, prefix):
    if text.startswith(prefix):
        return text[len(prefix):]
    return text

def parse_filled_in_contents(contents):
    """Parse filled in file contents and returns parsed dict.

    Return value will be::
        {
          "type": "bugfix",
          "category": "category",
          "description": "This is a description"
        }

    """
    if not contents.strip():
        return {}
    parsed = {}
    lines = iter(contents.splitlines())
    for line in lines:
        line = line.strip()
        if line.startswith('#'):
            continue
        if 'type' not in parsed and line.startswith('type:'):
            t = line[len('type:'):].strip()
            if t not in ['feature', 'bugfix', 'deprecation', 'removal',
                         'documentation']:
                raise Exception("Unsupported category %s" % t)
            parsed['type'] = t
        elif 'category' not in parsed and line.startswith('category:'):
            parsed['category'] = line[len('category:'):].strip()
        elif 'contributor' not in parsed and line.startswith('contributor:'):
            parsed['contributor'] = line[len('contributor:'):].strip()
        elif 'description' not in parsed and line.startswith('description:'):
            # Assume that everything until the end of the file is part
            # of the description, so we can break once we pull in the
            # remaining lines.
            first_line = line[len('description:'):].strip()
            full_description = '\n'.join([first_line] + list(lines))
            parsed['description'] = full_description.strip()
            break
    return parsed


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--type', dest='change_type',
                        default='', choices=('bugfix', 'feature',
                                             'deprecation', 'documentation'))
    parser.add_argument('-c', '--category', dest='category',
                        default='')
    parser.add_argument('-u', '--contributor', dest='contributor',
                        default='')
    parser.add_argument('-d', '--description', dest='description',
                        default='')
    parser.add_argument('-r', '--repo', default='aws/aws-sdk-java-v2',
                        help='Optional repo name, e.g: aws/aws-sdk-java')
    args = parser.parse_args()
    sys.exit(new_changelog_entry(args))


if __name__ == '__main__':
    main()
