#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This file is part of cepces.
#
# cepces is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cepces is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cepces.  If not, see <http://www.gnu.org/licenses/>.
#
# pylint: disable=broad-except,invalid-name
"""This is a submission helper for certmonger."""

import logging
import os
import sys
import traceback
import argparse
import requests
from cepces.certmonger.core import Result
from cepces.certmonger.operation import Operation
from cepces.config import Configuration
from cepces.core import Service
from cepces.log import init_logging


def main(global_overrides, krb5_overrides):
    """Main function."""
    # Initialize logging.
    init_logging()
    logger = logging.getLogger(__name__)

    # A dictionary of all supported operations.
    operations = {}

    # Ensure there's any operation to call.
    if 'CERTMONGER_OPERATION' not in os.environ:
        logger.error('Missing environment variable: CERTMONGER_OPERATION')

        sys.exit(Result.UNDERCONFIGURED)

    # Find all supported certmonger operations.
    for subclass in Operation.__subclasses__():
        operations[subclass.name] = subclass

    # Retrieve the operation name from the environment.
    operation = os.environ['CERTMONGER_OPERATION']
    result = Result.UNDERCONFIGURED

    # If the operation is available, call it. Otherwise, return an error code.
    if operation not in operations.keys():
        result = Result.UNSUPPORTED
    else:
        try:
            # Load the configuration and instantiate a service.
            config = Configuration.load(global_overrides=global_overrides,
                                        krb5_overrides=krb5_overrides)
            if config.openssl_seclevel and config.openssl_seclevel.isnumeric():
                requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:@SECLEVEL=%s' % config.openssl_seclevel
            service = Service(config)

            # Call the operation.
            operation = operations[operation](service)
            result = operation()
        except Exception:
            logger.error(traceback.format_exc())

    sys.exit(result)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='cepces submission helper for certmonger')
    parser.add_argument('--server',
        help='Hostname of the issuing certification authority')
    parser.add_argument('--auth',
        help='Authentication mechanism used for connecting to the service',
        choices=['Anonymous', 'Kerberos',
                 'UsernamePassword', 'Certificate'],
        default='Kerberos')
    parser.add_argument('--poll_interval',
        help='Time in seconds before re-checking if the certificate has been issued')
    parser.add_argument('--keytab', help='Use the specified keytab')
    parser.add_argument('--principals',
        help='A list of principals to try when requesting a ticket')
    parser.add_argument('--openssl-seclevel', help='The openssl security level')
    args = parser.parse_args()
    g_overrides = {}
    if args.server is not None:
        g_overrides['server'] = args.server
        g_overrides['auth'] = args.auth
        endpoint = 'https://%s/ADPolicyProvider_CEP_%s/service.svc/CEP' % \
                        (args.server, args.auth)
        g_overrides['endpoint'] = endpoint
    if args.poll_interval is not None:
        g_overrides['poll_interval'] = args.poll_interval
    if args.openssl_seclevel is not None:
        g_overrides['openssl_seclevel'] = args.openssl_seclevel
    k_overrides = {}
    if args.keytab is not None:
        k_overrides['keytab'] = args.keytab
    if args.principals is not None:
        k_overrides['principals'] = args.principals

    main(g_overrides, k_overrides)
