#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
This tool queries information from Cherwell via API.
'''

from __future__ import (absolute_import, division, print_function)

import os
import sys
import argparse
import yaml
import json
import time
import csv
from terminaltables import AsciiTable

from pycherwell.app_client import CherwellClient

__author__ = "Paul Greenberg @greenpau"
__version__ = '1.0.9'
__maintainer__ = "Paul Greenberg"
__email__ = "greenpau@outlook.com"
__status__ = "Alpha"
__pkg_name__ = str(os.path.basename(__file__))
__project_url = 'https://github.com/greenpau/pycherwell'
__project_description__ = 'Cherwell API Client'

def main():
    '''
    Main function.
    '''
    descr = '%s - %s\n\n' % (__pkg_name__, __project_description__)
    epil = '\ndocumentation: %s\n\n' % (__project_url)
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
                                     add_help=True, description=descr, epilog=epil)

    main_group = parser.add_argument_group(None)
    main_group.add_argument('-c', '--config', dest='config_file', default=None,
                            help='the path to configuration file')
    main_group.add_argument('--profile', dest='profile', default=None,
                            help='the name of configuration file section')
    main_group.add_argument('-o', '--output', metavar='output', dest='output', type=argparse.FileType('w'),
                            default=sys.stdout, help='Write to output file (or stdout)')

    action_arg_group = parser.add_argument_group('actions')
    action_group = action_arg_group.add_mutually_exclusive_group(required=True)
    action_group.add_argument('--get-service-info', dest='get_service_info', action='store_true', help='get service info')
    action_group.add_argument('--get-business-object-summaries', dest='get_business_object_summaries', action='store_true', help='get business object summaries')
    action_group.add_argument('--get-incidents', dest='get_incidents', action='store_true', help='get incidents')
    action_group.add_argument('--get-incident', dest='get_incident_by_id', metavar='ID', type=int,
                              help='get incident by id')
    action_group.add_argument('--get-teams', dest='get_teams', action='store_true', help='get teams')
    action_group.add_argument('--get-requestors', dest='get_requestors', action='store_true', help='get requestor')

    action_group.add_argument('--create-incident', dest='create_incident', action='store_true',
                              help='create an incident')

    action_group.add_argument('--get-journal', dest='get_journal', action='store_true',
                              help='get journal entries for an incident')
    action_group.add_argument('--add-journal-note', dest='add_journal_note', action='store_true',
                              help='add journal note')

    action_group.add_argument('--version', dest='display_version', action='store_true',
                              help='Display version')

    search_arg_group =  parser.add_argument_group('search arguments')
    search_arg_group.add_argument('--search-condition', dest='search_conditions', metavar='FIELD_NAME:OPERATOR:VALUE',
                                  action='append', help='Search conditions')
    search_arg_group.add_argument('--search-field', dest='search_fields', metavar='FIELD_NAME',
                                  action='append', help='Search fields')

    create_arg_group =  parser.add_argument_group('item creation arguments')
    create_arg_group.add_argument('--create-field', dest='create_fields', metavar='FIELD_NAME:VALUE',
                                  action='append', help='Field name and value for newly created items')
    create_arg_group.add_argument('--create-as', dest='create_as', metavar='FIELD_NAME:OPERATOR:VALUE',
                                  action='append', help='Requestor conditions')

    journal_arg_group =  parser.add_argument_group('journal arguments')
    journal_arg_group.add_argument('--journal-note', dest='journal_note', metavar='TEXT',
                                  help='the content of a journal note')

    filter_arg_group = parser.add_argument_group('miscellaneous')
    filter_arg_group.add_argument('--incident-id', dest='incident_id', metavar='ID', type=int,
                                help='incident id')
    filter_arg_group.add_argument('--filter', dest='obj_filters', metavar='KEY:VALUE',
                                  action='append', help='Object filters, e.g. field:regex')

    filter_arg_group.add_argument('--limit', dest='limit', metavar='NUMBER', type=int,
                                  default=None, help='limit the number of output items')
    filter_arg_group.add_argument('--without-header', dest='without_header',
                                  action='store_true', help='outputs data as a list of objects')
    filter_arg_group.add_argument('--summary-type', dest='summary_type',
                                  choices=['All', 'Major', 'Lookup', 'Supporting', 'Groups'],
                                  default='Major',
                                  help='Summary Object Type filter')

    main_group.add_argument('--rebase', dest='rebase', action='store_true',
                              help='Force specific action')
    main_group.add_argument('--format', dest='output_format', choices=['json', 'csv', 'yaml', 'text'],
                            default="json", help='Output format')
    main_group.add_argument('--debug', dest='enable_debug', action='store_true',
                              help='Enable debugging')
    args = parser.parse_args()

    opts = {}
    opts['output_format'] = args.output_format
    if args.limit:
        opts['limit'] = args.limit
    if args.without_header:
        opts['without_header'] = args.without_header
    try:
        tr, tc = os.popen('stty size', 'r').read().split()
        opts['terminal_rows'] = int(tr)
        opts['terminal_columns'] = int(tc)
    except:
        opts['terminal_rows'] = 0
        opts['terminal_columns'] = 0
    if args.search_conditions:
        opts['search_conditions'] = args.search_conditions
    if args.search_fields:
        opts['search_fields'] = args.search_fields
    if args.create_fields:
        opts['create_fields'] = args.create_fields
    if args.create_as:
        opts['create_as'] = args.create_as
    if args.incident_id:
        opts['incident_id'] = args.incident_id
    if args.journal_note:
        opts['journal_note'] = args.journal_note

    cli = CherwellClient()
    if args.enable_debug:
        cli.debug()

    if args.display_version:
        version = cli.get_version()
        args.output.write('%s %s\n%s\n' % (__pkg_name__, version, sys.version))
        return

    if args.config_file:
        cli.set_config_file(args.config_file)
    if args.profile:
        cli.set_profile(args.profile)
    cli.set_output_format(args.output_format)

    data = None
    if args.get_service_info:
        data = cli.get_service_info(opts)
    elif args.get_business_object_summaries:
        if args.summary_type:
            opts['summary_type'] = args.summary_type
        if args.rebase:
            opts['summary_type'] = 'All'
            opts['save_app_section'] = True
        data = cli.get_business_object_summaries(opts)
    elif args.get_incidents:
        data = cli.get_incidents(opts)
    elif args.get_incident_by_id:
        opts['incident_id'] = args.get_incident_by_id
        data = cli.get_incident(opts)
    elif args.get_teams:
        data = cli.get_teams(opts)
    elif args.create_incident:
        data = cli.create_incident(opts)
    elif args.get_requestors:
        data = cli.get_requestors(opts)
    elif args.add_journal_note:
        data = cli.add_journal_note(opts)
    elif args.get_journal:
        data = cli.get_journal(opts)
    else:
        raise Exception('parser', 'unsupported argument')

    if not data:
        return

    if args.output_format == 'yaml':
        yaml.dump(data, args.output, default_flow_style=False)
    elif args.output_format == 'csv':
        writer = csv.writer(args.output, dialect='excel')
        writer.writerows(data)
    elif args.output_format == 'text':
        table = AsciiTable(data)
        if args.get_journal:
            table.inner_heading_row_border = True
            table.inner_row_border = True
        args.output.write(table.table)
    else:
        json.dump(data, args.output, sort_keys=True, indent=4, separators=(',', ': '), default=str)
    args.output.write('\n')
    return

if __name__ == '__main__':
    main()
