#!/usr/bin/env python

import sys
from codebom.parseargs import parse_args
from codebom.bom import BomError
from codebom.lint import load_linted_bom
from codebom.verify import verify_bom
from codebom.scan import scan_bom
from codebom.analyze import analyze_bom
from codebom.graph import graph_bom
from ruamel import yaml
import os.path
import io

def bail(err):
    pos = err.pos
    location = "{}:{}:{}".format(pos.src, pos.line, pos.col)

    # Print an error message to stderr and exit the process.
    sys.exit("{}: error: {}".format(location, err.msg))

def print_graph(dot, out):
    """
    Print the 'dot' graph to out.name. The extension of out.name determines the format.
    """
    name, ext = os.path.splitext(out.name)
    fmt = ext[1:]
    if name == '<stdout>':
        out.write(dot.source)
        out.write('\n')
    elif fmt:
        out.write(dot.pipe(fmt))
    else:
        out.write(bytearray(dot.source, 'utf-8'))

if __name__ == '__main__':
    args = parse_args(sys.argv[1:])

    if args.f is None:
        if args.command == 'scan' and args.add:
            args.f = io.StringIO(u'')
            setattr(args.f, 'name', '<stdin>')
        else:
            sys.exit("codebom: error: '.bom.yaml' not found. Create one or point to an existing one with the '-f' option.")

    try:
        bom = load_linted_bom(args.f, args.f.name)

        if args.command == 'verify':
            is_source_dist = args.source_distribution
            check_origins = args.check_origins
            tgt_dir = os.path.dirname(args.o.name)
            data = verify_bom(bom, tgt_dir, is_source_dist=is_source_dist, check_origins=check_origins)
            args.o.write(yaml.dump(data, Dumper=yaml.RoundTripDumper))
            args.o.close()
        elif args.command == 'scan':
            data = scan_bom(
                bom,
                is_source_dist=args.source_distribution,
                scan_components=args.recursive,
                add_declarations=args.add,
                coalesce=args.coalesce,
                run_in_parallel=True)
            if args.add:
                args.o.write(yaml.dump(data, Dumper=yaml.RoundTripDumper))
                args.o.close()
        elif args.command == 'analyze':
            is_source_dist = args.source_distribution
            messages = analyze_bom(bom, is_source_dist=is_source_dist)
            if messages:
                args.o.write('\n'.join(messages))
                args.o.write('\n')
            args.o.close()
        elif args.command == 'graph':
            is_source_dist = args.source_distribution
            dot = graph_bom(bom, is_source_dist=is_source_dist)
            print_graph(dot, args.o)
    except BomError as err:
        bail(err)
