import json
import os
from datetime import date

from changelog.model import ReleaseChanges, ChangelogEntry, Version


def version_cmp(a,b):
    aa = [a.major, a.minor, a.patch, a.prerelease_version_number()]
    bb = [b.major, b.minor, b.patch, b.prerelease_version_number()]
    return cmp(bb,aa)

def load_all_released_changes(d):
    if not os.path.isdir(d):
        return []
    return [load_release_changes(os.path.join(d, fn)) for fn in os.listdir(d) if fn.endswith('.json')]

def load_release_changes(fn):
    with open(fn) as f:
        return parse_release_changes(json.loads(f.read()))

def load_unreleased_changes(d):
    if not os.path.exists(d):
        return None
    return ReleaseChanges(None, date.today().isoformat(), load_unreleased_entries(d))

def load_unreleased_entries(d):
    entries = []
    for f in [f for f in os.listdir(d) if f.endswith('.json')]:
        with open(os.path.join(d,f)) as e:
            entries.append(parse_changelog_entry(json.loads(e.read())))
    return entries

def parse_release_changes(changes_json):
    version = parse_version_string(changes_json['version'])
    date = changes_json['date']
    entries = [parse_changelog_entry(e) for e in changes_json['entries']]
    return ReleaseChanges(version, date, entries)

def parse_changelog_entry(entry_json):
    return ChangelogEntry(entry_json['type'], entry_json['category'], entry_json['description'],
                          entry_json.get('contributor'))

def parse_version_string(s):
    version_parts = [s for s in s.split('.')]
    prerelease = ""
    hyphen_index = version_parts[2].find('-')
    if hyphen_index != -1:
        p = version_parts[2]
        version_parts[2] = p[0:hyphen_index]
        prerelease = p[hyphen_index + 1:]
    return Version(int(version_parts[0]), int(version_parts[1]), int(version_parts[2]), prerelease)

class ReleaseChangesEncoder(json.JSONEncoder):
    def default(self, o):
        if type(o) is Version:
            # store as a "MAJOR.MINOR.PATCH" string so it's a little easier to
            # read the raw JSON
            return o.__str__()
        return o.__dict__

def marshall_release_changes(changes):
    return json.dumps(changes, indent=4, separators=(',', ': '), cls=ReleaseChangesEncoder)
