import argparse
import datetime
import re
import sys


CHANGELOG_START_RE = re.compile(r'^\#\# \[Unreleased\]')
CHANGELOG_END_RE = re.compile(r'^\#\# \[.*\] - \d{4}-\d{2}-\d{2}')
# if we come across a section header between two release section headers
# then we probably have an improperly formatted changelog
CHANGELOG_ERROR_RE = re.compile(r'^\#\# ')
SECTION_RE = re.compile(r'^\#\#\# (.*)$')
EMPTY_RE = re.compile(r'^\w*\*\w*$')
ENTRY_RE = re.compile(r'\* (.*)')
VALID_SECTIONS = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']


# allocate some entries to cut-down on merge conflicts
TEMPLATE = """### Added
  *
  *
  *

### Changed
  *
  *
  *

### Fixed
  *
  *
  *

"""


def main():
    print "i am broken"
    return 1
    parser = argparse.ArgumentParser()
    parser.add_argument('changelog')
    parser.add_argument('version')
    args = parser.parse_args()
    bump(changelog, version)


def bump(changelog, version):
    with open(changelog) as fp:
        lines = fp.readlines()

    start = []
    unreleased = []
    rest = []
    unreleased_start_found = False
    unreleased_end_found = False
    for line in lines:
        if not unreleased_start_found:
            start.append(line)
            if CHANGELOG_START_RE.search(line):
                unreleased_start_found = True
            continue
        if unreleased_end_found:
            rest.append(line)
            continue
        if CHANGELOG_END_RE.search(line):
            rest.append(line)
            unreleased_end_found = True
            continue
        if CHANGELOG_ERROR_RE.search(line):
            raise Exception(
                'Failed to parse {}: {}'.format(changelog, 'unexpected section header found'))
        unreleased.append(line)

    today = datetime.datetime.today()
    header = '## [{}] - {}\n'.format(version, today.strftime('%Y-%m-%d'))
    released = normalize(unreleased)
    if not released:
        # If we don't have anything in the Unreleased section, then leave the
        # changelog as it is and return None
        return

    changelog_data = (
        ''.join(start) +
        TEMPLATE +
        header +
        '\n'.join(released) + '\n\n'
        + ''.join(rest)
    )
    with open(changelog, 'w') as fp:
        fp.write(changelog_data)
    return '\n'.join(released) + '\n\n'


def normalize(lines):
    """Parse a changelog entry and output a normalized form"""
    sections = {}
    current_section_name = None
    current_section_contents = []
    for line in lines:
        line = line.strip()
        if not line or EMPTY_RE.match(line):
            continue
        match = SECTION_RE.match(line)
        if match:
            if current_section_contents:
                sections[current_section_name] = current_section_contents
            current_section_contents = []
            current_section_name = match.group(1)
            if current_section_name not in VALID_SECTIONS:
                raise ValueError("Section '{}' is not valid".format(current_section_name))
            continue
        match = ENTRY_RE.match(line)
        if match:
            current_section_contents.append(match.group(1))
            continue
        raise Exception('Something is wrong with line: {}'.format(line))
    if current_section_contents:
        sections[current_section_name] = current_section_contents

    output = []
    for section in VALID_SECTIONS:
        if section not in sections:
            continue
        output.append('### {}'.format(section))
        for entry in sections[section]:
            output.append(' * {}'.format(entry))
    return output


if __name__ == '__main__':
    sys.exit(main())