#!/usr/bin/env python
"""Synchronize authors and contributor metadata.

This script synchronizes the metadata provided in the CITATION.cff and
the contributors.yaml file with the metadata stored in the .zenodo.json
file.

All authors should be listed in the CITATION.cff file, while contributors
should be listed in the contributors.yaml file.
Both files use the [citation file-format][1] for [person objects][2].

[1] https://citation-file-format.github.io/
[2] https://citation-file-format.github.io/1.0.3/specifications/#/person-objects
"""
from dataclasses import dataclass

import click
import json
from ruamel.yaml import load, Loader


@dataclass
class Contributor:
    last_names: str
    first_names: str
    affiliation: str
    orcid: str = None

    @classmethod
    def from_citation_author(cls, **citation):
        return cls(
            last_names=citation.pop('family-names'),
            first_names=citation.pop('given-names'),
            **citation)

    def as_zenodo_creator(self):
        ret = dict(
            name='{} {}'.format(self.first_names, self.last_names),
            affiliation=self.affiliation)
        if self.orcid:
            ret['orcid'] = self.orcid.lstrip('https://orcid.org/')
        return ret


@click.command()
@click.pass_context
@click.option('--check', default=False, is_flag=True,
              help="Return with non-zero exit code if metadata needs to be updated.")
@click.option('-i', '--in-place', type=bool, is_flag=True,
              help="Modify metadata in place.")
def sync(ctx, in_place=False, check=True):

    with open('CITATION.cff', 'rb') as file:
        citation = load(file.read(), Loader=Loader)
        authors = [
            Contributor.from_citation_author(**author)
            for author in citation['authors']]

    with open('contributors.yaml', 'rb') as file:
        contributors = load(file.read(), Loader=Loader)['contributors']
        contributors = [Contributor.from_citation_author(
            **contributor) for contributor in contributors]

    with open('.zenodo.json', 'rb') as file:
        zenodo = json.loads(file.read())
        zenodo_updated = zenodo.copy()
        zenodo_updated['creators'] = [a.as_zenodo_creator() for a in authors]
        zenodo_updated['contributors'] = [c.as_zenodo_creator()
                                          for c in contributors if c not in authors]
        for key in ('version', 'keywords'):
            zenodo_updated[key] = citation[key]

    modified = json.dumps(zenodo, sort_keys=True) != json.dumps(zenodo_updated, sort_keys=True)
    if modified:
        if in_place:
            with open('.zenodo.json', 'wb') as file:
                file.write(json.dumps(zenodo_updated, indent=4, sort_keys=True).encode('utf-8'))
        else:
            click.echo(json.dumps(zenodo_updated, indent=4, sort_keys=True))
        if check:
            ctx.exit(1)
    else:
        click.echo("No changes.", err=True)


if __name__ == '__main__':
    sync()