#! /usr/bin/python3
import os
import sys
import yaml
import json
import pprint

try:
    # uiri/toml - new
    import toml
except ImportError:
    try:
        # avakar/pytoml - old (used by pip)
        import pytoml as toml
    except ImportError:
        toml = None

try:
    import bson
except ImportError:
    bson = None

fh_loaders = {
    "bson": lambda fh: next(bson.decode_file_iter(fh)),
    "json": lambda fh: json.load(fh),
    "toml": lambda fh: toml.load(fh),
    "yaml": lambda fh: yaml.safe_load(fh),
}

str_loaders = {
    #"bson": lambda buf: bson.decode(buf),
    "bson": lambda buf: bson.loads(buf),
    "json": lambda buf: json.loads(buf),
    "toml": lambda buf: toml.loads(buf),
    "yaml": lambda buf: yaml.load(buf),
}

fh_dumpers = {
    "bson": lambda arg, fh: fh.write(bson.encode(arg)),
    "toml": lambda arg, fh: toml.dump(arg, fh),
    "yaml": lambda arg, fh: yaml.dump(arg, stream=fh),
    "json": lambda arg, fh: json.dump(arg, fh),
    "pprint": lambda arg, fh: fh.write(pprint.pprint(arg)),
}

str_dumpers = {
    #"bson": lambda arg: bson.encode(arg),
    "bson": lambda arg: bson.dumps(arg),
    "json": lambda arg: json.dumps(arg),
    "toml": lambda arg: toml.dumps(arg),
    "yaml": lambda arg: yaml.dump(arg),
    "pprint": lambda arg: pprint.pprint(arg),
}

arg0 = os.path.basename(sys.argv[0])

if "2" not in arg0:
    if len(sys.argv) == 1 or sys.argv[1] == '--help':
        print(f"Usage {arg0} <from>2<to> [FILE]")
        print("\nUse '-' as FILE to indicate stdin")
        sys.exit(64)
    arg0 = sys.argv.pop(1)

itype, otype = arg0.split("2", 1)

if len(sys.argv) == 1 or sys.argv[1] == '-':
    ifh = sys.stdin
else:
    if sys.argv[1] == '--help':
        print(f"Usage: {arg0} [FILE]")
        print("\nUse '-' as FILE to indicate stdin")
        sys.exit(64)

    ifh = open(sys.argv[1])

if itype not in fh_loaders:
    print(f"Unknown input format {itype}", file=sys.stderr)
    sys.exit(64)

if otype not in str_dumpers:
    print(f"Unknown output format {otype}", file=sys.stderr)
    sys.exit(64)

data = fh_loaders[itype](ifh)

if otype == "bson":
    ofh = sys.stdout.buffer
    fh_dumpers[otype](data, ofh)
else:
    data = str_dumpers[otype](data)
    sys.stdout.write(data)
