#!/usr/bin/env python3

"""blast-radius:
  Quick hack to produce clarified terraform graph visualizations."""

# standard libraries
import re
import sys
import argparse
import os
import itertools

# 1st party libraries
from blastradius.handlers.dot import DotGraph, Format, DotNode
from blastradius.handlers.plan import Plan
from blastradius.handlers.apply import Apply
from blastradius.handlers.terraform import Terraform
from blastradius.server.server import app

def main():

    parser = parser = argparse.ArgumentParser(description='blast-radius: Interactive Terraform Graph Visualizations')
    parser.add_argument('directory', type=str, help='terraform configuration directory', default=os.getcwd(), nargs='?')
    parser.add_argument('--port', type=int, help='specify a port other than the default 5000', default=os.getenv('BLAST_RADIUS_PORT',5000))
    
    output_group = parser.add_mutually_exclusive_group()
    output_group.add_argument('--json', action='store_const', const=True, default=False, help='print a json representation of the Terraform graph')
    output_group.add_argument('--dot', action='store_const', const=True, default=False, help='print the graphviz/dot representation of the Terraform graph')
    output_group.add_argument('--svg', action='store_const', const=True, default=False, help='print the svg representation of the Terraform graph')
    output_group.add_argument('--serve', action='store_const', const=True, default=False, help='spins up a webserver with an interactive Terraform graph')
    
    parser.add_argument('--graph', type=str, help='`terraform graph` output (defaults to stdin)', default=sys.stdin)

    # options to limit, re-focus, and re-center presentation of larger graphs.
    constraint_group = parser.add_mutually_exclusive_group()
    constraint_group.add_argument('--module-depth', type=int, help='hide module details', required=False)
    constraint_group.add_argument('--focus', type=str, help='', required=False)
    constraint_group.add_argument('--center', type=str, help='', required=False)

    # TODO present changes, and animate `terraform apply'
    #parser.add_argument('--plan', type=str, help='terraform plan output', default=None)
    #parser.add_argument('--state', type=str, help='tfstate file', default=None)
    #parser.add_argument('--apply', type=str, help='terraform apply log', default=None)

    args = parser.parse_args()

    if args.serve:
        os.chdir(args.directory)
        app.run(host='0.0.0.0',port=args.port)
        sys.exit(0)
    
    elif args.json or args.dot or args.svg:
        if args.graph is sys.stdin:
            dot = DotGraph('', file_contents=sys.stdin.read())
        else:
            dot = DotGraph(args.graph)

        # we might not want to show every node in the depedency graph
        # specifying --module-depth is an easy way to limit detail
        if 'module_depth' in args and args.module_depth != None:
            if args.module_depth < 0:
                parser.print_help()
                sys.exit(1)
            dot.set_module_depth(args.module_depth)

        if 'center' in args and args.center:
            c_node = dot.get_node_by_name(args.center)
            if not c_node:
                parser.print_help()
                sys.exit(1)
            dot.center(c_node)

        if 'focus' in args and args.focus:
            f_node = dot.get_node_by_name(args.focus)
            if not f_node:
                parser.print_help()
                sys.exit(1)
            dot.focus(f_node)

        if args.json:
            tf = Terraform(args.directory)
            for node in dot.nodes:
                node.definition = tf.get_def(node)
        
        if args.json:
            print(dot.json())
        elif args.dot:
            print(dot.dot())
        elif args.svg:
            print(dot.svg())
    else:
        parser.print_help()


if __name__ == '__main__':
    main()
