#!python
from states import *
import argparse
import os


def init(args):
    r, l = RemoteState(args.profile), LocalState(args.filename)
    l.save(r.get(flat=False, paths=args.path))


def pull(args):
    dictfilter = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
    r, l = RemoteState(args.profile), LocalState(args.filename)
    diff = helpers.FlatDictDiffer(r.get(paths=args.path), l.get(paths=args.path))
    if args.force:
        ref_set = diff.changed().union(diff.removed()).union(diff.unchanged())
        target_set = diff.added()
    else:
        ref_set = diff.unchanged().union(diff.removed())
        target_set = diff.added().union(diff.changed())
    state = dictfilter(diff.ref, ref_set)
    state.update(dictfilter(diff.target, target_set))
    l.save(helpers.unflatten(state))


def apply(args):
    r, _, diff = plan(args)

    print "\nApplying changes..."
    try:
        r.apply(diff)
    except Exception as e:
        print "Failed to apply changes to remote:", e
    print "Done."


def plan(args):
    r, l = RemoteState(args.profile), LocalState(args.filename)
    diff = helpers.FlatDictDiffer(r.get(paths=args.path), l.get(paths=args.path))

    if diff.differ:
        diff.print_state()
    else:
        print "Remote state it up to date."

    return r, l, diff


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', help='local state yml file', action='store', dest='filename', default='parameters.yml')
    parser.add_argument('--path', '-p', action='append', help='filter SSM path')
    parser.add_argument('--profile', help='AWS profile name', action='store', dest='profile')
    subparsers = parser.add_subparsers(help='commands')

    parser_plan = subparsers.add_parser('plan', help='display changes between local and remote states')
    parser_plan.set_defaults(func=plan)

    parser_init = subparsers.add_parser('init', help='create or overwrite local state snapshot')
    parser_init.set_defaults(func=init)

    parser_pull = subparsers.add_parser('pull', help='pull updates from remote state')
    parser_pull.set_defaults(func=pull)
    parser_pull.add_argument('--force', help='overwrite local changes', action='store_true', dest='force')

    parser_apply = subparsers.add_parser('apply', help='apply diff to the remote state')
    parser_apply.set_defaults(func=apply)

    args = parser.parse_args()
    args.path = args.path if args.path else ['/']

    if args.filename == 'parameters.yml':
        if not args.profile:
            if 'AWS_PROFILE' in os.environ:
                args.filename = os.environ['AWS_PROFILE'] + '.yml'
        else:
            args.filename = args.profile + '.yml'
    args.func(args)
