#!/usr/bin/env python
#                                                            _
# PACS ToolKit findscu (and possible movescu) Wrapper
#
# (c) 2016-2019 Fetal-Neonatal Neuroimaging & Developmental Science Center
#                   Boston Children's Hospital
#
#              http://childrenshospital.org/FNNDSC/
#                        dev@babyMRI.org
#

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '../'))


from    argparse            import RawTextHelpFormatter
from    argparse            import ArgumentParser
from    terminaltables      import SingleTable
from    pfmisc._colors      import Colors
import  json
import  pypx
import  socket
import  pudb

str_defIP   = [l for l in (
                [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2]
                if not ip.startswith("127.")][:1],
                    [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close())
                for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0]

str_name    = "px-report"
str_version = "3.2.26"
str_desc    = Colors.CYAN + """
                                                              _   
                                                             | |  
         _ __  __  __ ______  _ __   ___  _ __    ___   _ __ | |_ 
        | '_ \ \ \/ /|______|| '__| / _ \| '_ \  / _ \ | '__|| __|
        | |_) | >  <         | |   |  __/| |_) || (_) || |   | |_ 
        | .__/ /_/\_\        |_|    \___|| .__/  \___/ |_|    \__|
        | |                              | |                      
        |_|                              |_|                      


                        PACS ToolKit Wrapper
                         CLI reporting tool

                       -- version """ + \
             Colors.YELLOW + str_version + Colors.CYAN + """ --

    ``px-report`` is a module / script that provides functionality for
    reporting on several px-* family tools

    ``px-report`` is mostly used in conjunction with ``px-find`` (and
    ``px-status``) and it consumes/parses/generates CLI/text reports
    based on the JSON payload return of the find/status/move operations.

    The application/module is suitable for consuming JSON return from
    calling other functions either from the CLI or a web-intermediary.

""" + Colors.NO_COLOUR

def synopsis(ab_shortOnly = False):
    scriptName = os.path.basename(sys.argv[0])
    shortSynopsis =  Colors.YELLOW + '''
    NAME

	    %s

        - PACS report

    SYNOPSIS

            _script mode_:
            px-report
                [--reportData <JSONdump>]                           \\
                [--reportDataFile <file>]                           \\
                [--seriesSpecial <type>]                            \\
                [--colorize light|dark]                             \\
                [--printReport tabular|rawText|csv|json]            \\
                [--reportLayout <JSONstructure>]                    \\
                [--reportHeaderStudyTags <commaListOfStudyTags>]    \\
                [--reportHeaderSeriesTags <commaListOfSeriesTags>]  \\
                [--reportBodySeriesTags <commaListOfSeriesTags>]    \\
                [--csvPrintHeaders] [--csvSeparator <sep>]          \\
                [--csvSummarise]                                    \\
                [-x|--desc]                                         \\
                [-y|--synopsis]                                     \\
                [--version]                                         \\
                [--debugToDir <dir>]                                \\
                [--verbosity <level>]

    ''' % scriptName + Colors.NO_COLOUR

    description = Colors.LIGHT_GREEN + '''

    DESCRIPTION

        ``px-report`` typically consumes the `stdout` JSON string generated
        by an upstream process (often ``px-find``) and generates various
        CLI reports.

    ARGS

        [--reportData <JSONdump>]
        This argument is used to store JSON data that is either read from
        stdin or from the [--reportDataFile]. It is not really meant to
        be a usable CLI.

        [--reportDataFile <file>]
        A file containing JSON report data.

        [--reportLayout <JSONstructure>]
        If specified, print only the JSON specified result tags from either the
        STUDY or SERIES level. This argument is a JSON string value that provides
        the template for the report.

        [--seriesSpecial <type>]
        Use the internal 'series<type>_print' method to inject additional
        information into the return. This will create a new tag called <type>
        in the report body. Currently only supported for <status> handling.

        [--reportHeaderStudyTags <commaListOfStudyTags>]
        If specified, set the list of Study Tags in the report header to the
        pecified values.

        [--reportHeaderSeriesTags <commaListOfSeriesTags>]
        If specified, set the list of Series Tags in the report header to
        the specified values.

        [--reportBodySeriesTags <commaListOfSeriesTags>]
        If specified, set the list of Series Tags in the report body to
        the specified values.

        [--colorize 'light'|'dark']
        An optional directive to colorize the report output, either for 'light'
        or 'dark' consoles.

        [--ReportLineOverwrite]
        If specified, use the "special" DICOM tag value for ReportLineOverwrite
        for the report body.

        [--printReport tabular|rawText|json|csv]
        If specified, pretty print a report in a variety of formats.

        [--csvPrintHeaders]
        If specified, print a row of headers. Only meaningful for CSV reports.

        [--csvSeparator <sep>]
        If specified, use <sep> as columng separator. Only meaningful for CSV
        reports.

        [--csvSummarize]
        If specified, summarize the CSV table into one-entry-per study.

        [--waitForUserTerminate]
        If specified, wait at program conclusion for explicit user termination.
        This is useful in dockerized runs since PACS data might still be
        in flight when the program ends, and terminating the program then
        will result in non reception of outstanding data.

        Note, if running in a container, e.g. via PACS_QR.sh, be sure to also
        specify a '-D' for debugging in conjunction with this flag. The '-D'
        runs the container in interactive tty mode, allowing for user tty
        input to be correctly interpreted.

        [--json]
        If specified, pass the JSON reportData through to the output. This is
        useful for piping together chains of compute.

        [-x|--desc]
        Provide an overview help page.

        [-y|--synopsis]
        Provide a synopsis help summary.

        [--version]
        Print internal version number and exit.

        [--debugToDir <dir>]
        A directory to contain various debugging output -- these are typically
        JSON object strings capturing internal state. If empty string (default)
        then no debugging outputs are captured/generated. If specified, then
        ``pfcon`` will check for dir existence and attempt to create if
        needed.

        [-v|--verbosity <level>]
        Set the verbosity level. "0" typically means no/minimal output. Allows for
        more fine tuned output control as opposed to '--quiet' that effectively
        silences everything.

    EXAMPLES

        px-find --PatientID 4777764 | px-report --printReport csv

    ''' + Colors.NO_COLOUR

    if ab_shortOnly:
        return shortSynopsis
    else:
        return shortSynopsis + description


parser = ArgumentParser(
            description         = str_desc,
            formatter_class     = RawTextHelpFormatter
        )

# the main report data to interpret
parser.add_argument(
    '--reportData',
    action  = 'store',
    dest    = 'reportData',
    type    = str,
    default = '',
    help    = 'JSON report from upstream process')

parser.add_argument(
    '--reportDataFile',
    action  = 'store',
    dest    = 'reportDataFile',
    type    = str,
    default = '',
    help    = 'JSON report contained in file from upstream process')

# db access settings
parser.add_argument(
    '--dblogbasepath',
    action  = 'store',
    dest    = 'dblogbasepath',
    type    = str,
    default = '/tmp/log',
    help    = 'path to base dir of receipt database')

# Behavioural settings
parser.add_argument(
    '--colorize',
    action  = 'store',
    dest    = 'colorize',
    type    = str,
    default = '',
    help    = 'Colorize report output: use "dark" or "light"')
parser.add_argument(
    '--printReport',
    action  = 'store',
    dest    = 'printReport',
    type    = str,
    default = '',
    help    = 'The returned report component to print')
parser.add_argument(
    '--csvPrintHeaders',
    action  = 'store_true',
    dest    = 'csvPrintHeaders',
    default = False,
    help    = 'If specified, print CSV column headers')
parser.add_argument(
    '--csvPrettify',
    action  = 'store_true',
    dest    = 'csvPrettify',
    default = False,
    help    = 'If specified, pretty print CSV table')
parser.add_argument(
    '--csvSummarize',
    action  = 'store_true',
    dest    = 'csvSummarize',
    default = False,
    help    = 'If specified, summarize CSV table')
parser.add_argument(
    '--csvSeparator',
    action  = 'store',
    dest    = 'csvSeparator',
    type    = str,
    default = '|',
    help    = 'The column separator for CSV reports')
parser.add_argument(
    '--reportLayout',
    action  = 'store',
    dest    = 'reportTags',
    type    = str,
    default = '',
    help    = 'The tag results to print at the STUDY or SERIES level')
parser.add_argument(
    '--seriesSpecial',
    action  = 'store',
    dest    = 'seriesSpecial',
    type    = str,
    default = '',
    help    = 'Add a SERIES tag <seriesType> and set value to internal method result.')
parser.add_argument(
    '--reportHeaderStudyTags',
    action  = 'store',
    dest    = 'reportHeaderStudyTags',
    type    = str,
    default = '',
    help    = 'A comma separated list of Study Tags to show in the report header')
parser.add_argument(
    '--reportHeaderSeriesTags',
    action  = 'store',
    dest    = 'reportHeaderSeriesTags',
    type    = str,
    default = '',
    help    = 'A comma separated list of Series Tags to show in the report header')
parser.add_argument(
    '--reportBodySeriesTags',
    action  = 'store',
    dest    = 'reportBodySeriesTags',
    type    = str,
    default = '',
    help    = 'A comma separated list of Series Tags to show in the report body')

parser.add_argument(
    "-v", "--verbosity",
    help    = "verbosity level for app",
    dest    = 'verbosity',
    type    = int,
    default = 1)
parser.add_argument(
    "-x", "--desc",
    help    = "long synopsis",
    dest    = 'desc',
    action  = 'store_true',
    default = False
)
parser.add_argument(
    "-y", "--synopsis",
    help    = "short synopsis",
    dest    = 'synopsis',
    action  = 'store_true',
    default = False
)
parser.add_argument(
    '--version',
    help    = 'if specified, print version number',
    dest    = 'b_version',
    action  = 'store_true',
    default = False
)
parser.add_argument(
    '--json',
    help    = 'if specified, dump the input JSON again to output',
    dest    = 'b_json',
    action  = 'store_true',
    default = False
)

args        = parser.parse_args()

if args.desc or args.synopsis:
    print(str_desc)
    if args.desc:
        str_help     = synopsis(False)
    if args.synopsis:
        str_help     = synopsis(True)
    print(str_help)
    sys.exit(1)

if args.b_version:
    print("Version: %s" % str_version)
    sys.exit(1)

if len(args.reportData):
    args.reportData     = json.loads(args.reportData)
elif len(args.reportDataFile):
    with open(args.reportDataFile) as reportFile:
        args.reportData     = json.load(reportFile)
else:
    # Read from input stream
    str_inputPipe           = ''
    for line in sys.stdin:
        str_inputPipe += line

    args.reportData     = json.loads(str_inputPipe)

report                  = pypx.report(vars(args))

sys.exit(0)
