#!/usr/bin/env python

"""
Tool for manipulating the state of edges.

  edge_conf takes the required mode parameter and sets the mode of an
 edge to the corresponding mode. The behaviours of these modes can be
 seen in edgemanage/const.py.

"""

__author__="nosmo@nosmo.me"

from edgemanage import EdgeState, util
from edgemanage.const import VALID_MODES, CONFIG_PATH

import argparse
import getpass
import logging
import logging.handlers
import os
import sys

import yaml

def main(dnet, edgename, config, mode, comment=None, no_syslog=False):

    with open(os.path.join(config["edgelist_dir"], dnet)) as edge_f:
        edge_list = [ i.strip() for i in edge_f.read().split("\n") if i.strip() and not i.startswith("#") ]

    if edgename not in edge_list:
        raise KeyError("Edge %s is not in the edge list of %s" % (edgename, dnet))

    if not os.path.exists(os.path.join(config["healthdata_store"], "%s.edgestore" % edgename)):
        raise Exception("Edge %s is not initialised yet - not setting status" % edgename)

    try:
        edge_state = EdgeState(edgename, config["healthdata_store"], nowrite=False)
    except Exception as e:
        raise SystemExit("failed to load state for edge %s: %s" % (edgename, str(e)))

    edge_state.set_mode(mode)

    if comment:
        run_user = getpass.getuser()
        if os.getenv("SUDO_USER"):
            run_user = os.getenv("SUDO_USER")
        comment = "[%s] %s" % (run_user, comment)

        edge_state.set_comment(comment)

        if not no_syslog:
            handler = logging.handlers.SysLogHandler(
                facility=logging.handlers.SysLogHandler.LOG_DAEMON)
            logger = logging.getLogger('edge_conf')
            logger.setLevel(logging.INFO)
            logger.addHandler(handler)
            logger.info("Edge %s changed mode to %s with comment %s", edgename, mode, comment)
    elif mode == "available":
        edge_state.unset_comment()

    print "Set mode for %s to %s" % (edgename, mode)

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description='Configure Deflect edge mode.')
    parser.add_argument("--config", "-c", dest="config_path", action="store",
                        help="Path to configuration file (defaults to %s)" % CONFIG_PATH,
                        default=CONFIG_PATH)
    parser.add_argument("--dnet", "-A", dest="dnet", action="store",
                        help="Specify DNET (mandatory)", required=True)
    parser.add_argument("--no-syslog", dest="nosyslog", action="store_true",
                        help="Don't log comments to syslog", default=False)
    parser.add_argument("--comment", "-C", dest="comment", action="store",
                        help=("Comment about your change (required for all "
                              "modes other than available)"))
    parser.add_argument("--mode", "-m", dest="mode", action="store", default=None,
                        help="Set mode", required=True,
                        choices=VALID_MODES)
    parser.add_argument("edge", action="store",
                        help="Edge to configure", nargs=1)
    args = parser.parse_args()

    if not args.dnet and not args.edge:
        raise Exception("Arguments must specify either a DNET or a specific edge")

    if args.mode != "available" and not args.comment:
        sys.stderr.write(("Comment required for mode to "
                          "be changed to anything but available.\n"))
        sys.exit(1)


    with open(args.config_path) as config_f:
        config = yaml.safe_load(config_f.read())

    lock_f = open(config["lockfile"], "w")
    if not util.acquire_lock(lock_f):
        sys.stderr.write("Couldn't acquire lockfile - not executing.\n")
        sys.exit(2)

    main(args.dnet, args.edge[0], config, args.mode, args.comment, args.nosyslog)
    lock_f.close()
