#!/usr/bin/env python

###############################################################################
# (c) Copyright 2018 CERN                                                     #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
'''
Command line client for CVMFS Reports generator

:author: Chitic Stefan-Gabriel
'''
from __future__ import print_function
import logging
import optparse
import os
import sys
import traceback


from lbCVMFSReporting.ReportEmailer import LbReportEmailer
from lbCVMFSReporting.LbReport import LbCVMFSReport

# Class for known install exceptions
###############################################################################


class LbCVMFSReportsException(Exception):
    """ Custom exception

    :param msg: the exception message
    """

    def __init__(self, msg):
        """ Constructor for the exception """
        # super(LbCVMFSReportsException, self).__init__(msg)
        Exception.__init__(self, msg)


# Classes and method for command line parsing
###############################################################################


class LbCVMFSReportsOptionParser(optparse.OptionParser):
    """ Custom OptionParser to intercept the errors and rethrow
    them as LbCVMFSReportsExceptions """

    def error(self, msg):
        """
        Arguments parsing error message exception handler

        :param msg: the message of the exception
        :return: Raises LbCVMFSReportsException with the exception message
        """
        raise LbCVMFSReportsException("Error parsing arguments: " + str(msg))

    def exit(self, status=0, msg=None):
        """
        Arguments parsing error message exception handler

        :param status: the status of the application
        :param msg: the message of the exception
        :return: Raises LbCVMFSReportsException with the exception message
        """
        raise LbCVMFSReportsException("Error parsing arguments: " + str(msg))


class LbCVMFSReportsClient(object):
    """ Main class for the tool """

    MODE_UPDATE = "update"
    MODE_EMAIL = "email"

    MODES = [MODE_UPDATE, MODE_EMAIL]

    SENDER = 'stefan-gabriel.chitic@cern.ch'
    DEST = ['lhcb-cvmfs-librarians@cern.ch']
    SUBJECT = "Report for nightlies installation on CVMFSDev"

    def __init__(self, configType, arguments=None,
                 dry_run=False, prog="LbCVMFSReports"):
        """ Common setup for both clients """
        self.configType = configType
        self.log = logging.getLogger(__name__)
        self.arguments = arguments
        self.prog = prog

        parser = LbCVMFSReportsOptionParser(usage=usage(self.prog))
        # parser.disable_interspersed_args()

        self.parser = parser

    def main(self):
        """ Main method for the ancestor:
        call parse and run in sequence

        :returns: the return code of the call
        """
        rc = 0
        try:
            opts, args = self.parser.parse_args(self.arguments)

            # Getting the function to be invoked
            self.run(opts, args)

        except LbCVMFSReportsException as lie:
            print("ERROR: " + str(lie), file=sys.stderr)
            self.parser.print_help()
            rc = 1
        except:
            print("Exception in lbCVMFSReports:", file=sys.stderr)
            print('-'*60, file=sys.stderr)
            traceback.print_exc(file=sys.stderr)
            print('-'*60, file=sys.stderr)
            rc = 1
        return rc

    def run(self, opts, args):
        """ Main method for the command

        :param opts: The option list
        :param args: The arguments list
        """
        # Parsing first argument to check the mode
        if len(args) == 2:
            cmd = args[0].lower()
            if cmd in LbCVMFSReportsClient.MODES:
                mode = cmd
            else:
                raise LbCVMFSReportsException("Unrecognized command: %s" % args)
        else:
            raise LbCVMFSReportsException("Argument list too short")

        # Now executing the command
        if mode == LbCVMFSReportsClient.MODE_EMAIL:
            reporter = LbReportEmailer(args[1], self.SENDER, self.DEST,
                                       self.SUBJECT)
        elif mode == LbCVMFSReportsClient.MODE_UPDATE:
            reporter = LbCVMFSReport(args[1])
            reporter.sendToNightlies()
        else:
            self.log.error("Command not recognized: %s" % mode)


# Usage for the script
###############################################################################
def usage(cmd):
    """ Prints out how to use the script...

    :param cmd: the command executed
    """
    cmd = os.path.basename(cmd)
    return """\n%(cmd)s -  generates raport for give date'

It can be used in the following ways:

%(cmd)s email <date>
Emails the reports

%(cmd)s updates <date>
Updates the nightlies dashboard

""" % {"cmd": cmd}


def LbCVMFSReports(configType="LHCbConfig", prog="LbCVMFSReports"):
    """
    Default caller for command line LbCVMFSReports client
    :param configType: the configuration used
    :param prog: the name of the executable
    """
    logging.basicConfig(format="%(levelname)-8s: %(message)s")
    logging.getLogger().setLevel(logging.WARNING)
    sys.exit(LbCVMFSReportsClient(configType, prog=prog).main())

# Main just chooses the client and starts it
if __name__ == "__main__":
    LbCVMFSReports()
