#
#
#

from argparse import ArgumentParser as _Base
from logging import DEBUG, INFO, WARNING, Formatter, StreamHandler, getLogger
from logging.config import dictConfig
from logging.handlers import SysLogHandler
from sys import stderr, stdout

from yaml import safe_load

from octodns import __version__


class ArgumentParser(_Base):
    '''
    Manages argument parsing and adds some defaults and takes action on them.

    Also manages logging setup.
    '''

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def parse_args(self, default_log_level=INFO):
        version = f'octoDNS {__version__}'
        self.add_argument(
            '--version',
            action='version',
            version=version,
            help='Print octoDNS version and exit',
        )
        self.add_argument(
            '--log-stream-stdout',
            action='store_true',
            default=False,
            help='Log to stdout instead of stderr',
        )
        _help = 'Send logging data to syslog in addition to stderr'
        self.add_argument(
            '--log-syslog', action='store_true', default=False, help=_help
        )
        self.add_argument(
            '--syslog-device', default='/dev/log', help='Syslog device'
        )
        self.add_argument(
            '--syslog-facility', default='local0', help='Syslog facility'
        )

        _help = 'Increase verbosity to get details and help track down issues'
        self.add_argument(
            '--debug', action='store_true', default=False, help=_help
        )

        _help = 'Decrease verbosity to show only warnings, errors, and the plan'
        self.add_argument(
            '--quiet', action='store_true', default=False, help=_help
        )

        _help = 'Configure logging with a YAML file, see https://docs.python.org/3/library/logging.config.html#logging-config-dictschema for schema details'
        self.add_argument('--logging-config', default=False, help=_help)

        args = super().parse_args()
        self._setup_logging(args, default_log_level)
        return args

    def _setup_logging(self, args, default_log_level):
        if args.logging_config:
            with open(args.logging_config) as fh:
                config = safe_load(fh.read())
            dictConfig(config)
            # if we're provided a logging_config we won't do any of our normal
            # configuration
            return

        fmt = '%(asctime)s [%(thread)d] %(levelname)-5s %(name)s %(message)s'
        formatter = Formatter(fmt=fmt, datefmt='%Y-%m-%dT%H:%M:%S ')
        stream = stdout if args.log_stream_stdout else stderr
        handler = StreamHandler(stream=stream)
        handler.setFormatter(formatter)
        logger = getLogger()
        logger.addHandler(handler)

        if args.log_syslog:
            fmt = (
                'octodns[%(process)-5s:%(thread)d]: %(name)s '
                '%(levelname)-5s %(message)s'
            )
            handler = SysLogHandler(
                address=args.syslog_device, facility=args.syslog_facility
            )
            handler.setFormatter(Formatter(fmt=fmt))
            logger.addHandler(handler)

        logger.level = default_log_level
        if args.debug:
            logger.level = DEBUG
        elif args.quiet:
            logger.level = WARNING
            # we still want plans to come out during quite so set the plan
            # logger output to info in case the PlanLogger is being used
            getLogger('Plan').setLevel(INFO)
