#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2016 Bitergia
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Authors:
#     Santiago Dueñas <sduenas@bitergia.com>
#

import argparse
import configparser
import logging
import os.path
import sys

import perceval
import perceval.backends


PERCEVAL_USAGE_MSG = \
"""%(prog)s [-c <file>] [-g] <backend> [<args>] | --help """

PERCEVAL_DESC_MSG = \
"""Send Sir Perceval on a quest to retrieve and gather data from software
repositories.

Repositories are reached using specific backends. The most common backends
are:

    askbot           Fetch questions and answers from Askbot site
    bugzilla         Fetch bugs from a Bugzilla server
    bugzillarest     Fetch bugs from a Bugzilla server (>=5.0) using its REST API
    confluence       Fetch contents from a Confluence server
    discourse        Fetch posts from Discourse site
    gerrit           Fetch reviews from a Gerrit server
    git              Fetch commits from Git
    github           Fetch issues from GitHub
    gmane            Fetch messages from Gmane
    jenkins          Fetch builds from a Jenkins server
    jira             Fetch issues from JIRA issue tracker
    mbox             Fetch messages from MBox files
    mediawiki        Fetch pages and revisions from a MediaWiki site
    meetup           Fetch events from a Meetup group
    phabricator      Fetch tasks from a Phabricator site
    pipermail        Fetch messages from a Pipermail archiver
    redmine          Fetch issues from a Redmine server
    stackexchange    Fetch questions from StackExchange sites
    supybot          Fetch messages from Supybot log files
    telegram         Fetch messages from the Telegram server

optional arguments:
  -h, --help            show this help message and exit
  -c FILE, --config FILE
                        set configuration file
  -g, --debug           set debug mode on
"""

PERCEVAL_EPILOG_MSG = \
"""Run '%(prog)s <backend> --help' to get information about a specific backend."""

# Logging formats
PERCEVAL_LOG_FORMAT = "[%(asctime)s] - %(message)s"
PERCEVAL_DEBUG_LOG_FORMAT = "[%(asctime)s - %(name)s - %(levelname)s] - %(message)s"


def main():
    args = parse_args()

    # Read default parameters from a configuration file
    if args.config_file:
        defaults = read_config_file(args.config_file, args.backend)
    else:
        defaults = {}

    _, PERCEVAL_CMDS = perceval.find_backends(perceval.backends)

    if args.backend not in PERCEVAL_CMDS:
        raise RuntimeError("Unknown backend %s" % args.backend)

    configure_logging(args.debug)

    logging.info("Sir Perceval is on his quest.")

    klass = PERCEVAL_CMDS[args.backend]
    cmd = klass(*args.backend_args)
    cmd.run()

    logging.info("Sir Perceval completed his quest.")


def parse_args():
    """Parse command line arguments"""

    parser = argparse.ArgumentParser(usage=PERCEVAL_USAGE_MSG,
                                     description=PERCEVAL_DESC_MSG,
                                     epilog=PERCEVAL_EPILOG_MSG,
                                     formatter_class=argparse.RawDescriptionHelpFormatter,
                                     add_help=False)

    parser.add_argument('-h', '--help', action='help',
                       help=argparse.SUPPRESS)
    parser.add_argument('-c', '--config', dest='config_file',
                        default=os.path.expanduser('~/.perceval/perceval.cfg'),
                        help=argparse.SUPPRESS)
    parser.add_argument('-g', '--debug', dest='debug',
                        action='store_true',
                        help=argparse.SUPPRESS)

    parser.add_argument('backend', help=argparse.SUPPRESS)
    parser.add_argument('backend_args', nargs=argparse.REMAINDER,
                        help=argparse.SUPPRESS)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    return parser.parse_args()


def read_config_file(filepath, backend):
    """Read a Perceval configuration file.

    This function reads common and `backend` configuration parameters
    from the given file.

    :param filepath: path to the configuration file
    :param backend: name of the backend which its parameters will be read

    :returns: a configuration parameters dictionary
    """
    config = configparser.SafeConfigParser()
    config.read(filepath)

    args = {}
    sections = ['cache', backend]

    for section in sections:
        if section in config.sections():
            d = dict(config.items(section))
            args.update(d)

    return args

def configure_logging(debug=False):
    """Configure Perceval logging

    The function configures the log messages produced by Perceval.
    By default, log messages are sent to stderr. Set the parameter
    `debug` to activate the debug mode.

    :param debug: set the debug mode
    """
    if not debug:
        logging.basicConfig(level=logging.INFO,
                            format=PERCEVAL_LOG_FORMAT)
        logging.getLogger('requests').setLevel(logging.WARNING)
        logging.getLogger('urrlib3').setLevel(logging.WARNING)
    else:
        logging.basicConfig(level=logging.DEBUG,
                            format=PERCEVAL_DEBUG_LOG_FORMAT)


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        s = "\n\nReceived Ctrl-C or other break signal. Exiting.\n"
        sys.stderr.write(s)
        sys.exit(0)
