#!/usr/bin/env python3
"""Read an explicitly supplied fact package; emit only a derived JSON view."""
import argparse
import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'src'))
from arb_graph import GraphError, project, check_versions


def pairs(items):
    out = {}
    for key, value in items:
        if key in out: raise GraphError('duplicate JSON key: ' + key)
        out[key] = value
    return out


def read(path):
    if any(p.is_symlink() for p in [path, *path.parents]):
        raise GraphError('symlink input refused')
    data = json.loads(path.read_text(encoding='utf-8'), object_pairs_hook=pairs,
                      parse_constant=lambda value: (_ for _ in ()).throw(GraphError('nonfinite JSON number')))
    if not isinstance(data, dict): raise GraphError('input must be an object')
    return data


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('input', type=Path)
    parser.add_argument('--previous', type=Path)
    args = parser.parse_args()
    try:
        data = read(args.input)
        if args.previous:
            errors = check_versions(read(args.previous), data)
            if errors: raise GraphError('; '.join(errors))
        output = project(data, str(args.input.absolute()))
        print(json.dumps(output, sort_keys=True, ensure_ascii=False, indent=2, allow_nan=False))
        return 0
    except (OSError, ValueError, TypeError, KeyError, AttributeError) as error:
        print(f'arb-graph: ERROR: {error}; input unchanged; repair source and retry', file=sys.stderr)
        return 2


if __name__ == '__main__':
    raise SystemExit(main())
