#!/usr/bin/python3

import argparse,os,git,re,semver

folder = "install"
p = re.compile('^((.{1,2}) )?(.+): (.+)$')

def parse_version(v):
    v = v.removeprefix("v").split(".")
    pre = None
    if len(v) > 3:
        pre = v[3]
    return semver.Version(major=v[0], minor=v[1], patch=v[2], prerelease=pre)

def parse_rule(rule):
    m = p.match(rule)
    op = m.group(2)
    if op is None:
        op = '<='
    v = m.group(3)
    ref = m.group(4)
    return op, v, ref 

def get_rev(discourse_version, rules, kept_rev):
    rule = next(rules, None)
    if rule is None:
        return kept_rev

    op, v, rev = parse_rule(rule)
    version = parse_version(v)
    r = discourse_version.compare(version)
    if r == 1 or (r == 0 and op == "<"):
        return kept_rev

    return get_rev(discourse_version, rules, rev)


def get_rules(repo):
    try:
        blob = repo.head.commit.tree[".discourse-compatibility"]
    except:
        return iter([])
    rules = [
        line.decode() for line in blob.data_stream.read().splitlines()
    ]
    return iter(rules)

def main(args):
    discourse_version = parse_version(args.version)
    print("Updating plugins for Discourse %s" % discourse_version)
    for d in os.listdir(folder):
        try:
            repo = git.Repo(folder + "/" + d)
            repo.remotes.origin.pull()
            rules = get_rules(repo)
            ref = get_rev(discourse_version, rules, repo.head.commit.hexsha)
            repo.head.reset(commit=ref, working_tree=True)
            log = d.ljust(40) + ref
            repo.active_branch
            if ref == repo.remotes.origin.refs.HEAD.commit.hexsha:
                log += " (head)"
            print(log)
        except Exception as e:
            print(d.ljust(40)+"failed")
            print(e)
            exit(1)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Helper script to manage Discourse plugins.')
    parser.add_argument("version")
    args = parser.parse_args()
    main(args)