#!python
""" gpu-ls  -  Displays details about installed and compatible GPUs

    Part of the rickslab-gpu-utils package which includes gpu-ls, gpu-mon, gpu-pac, and
    gpu-plot.

    This utility displays most relevant parameters for installed and compatible GPUs. The
    default behavior is to list relevant parameters by GPU.  OpenCL platform information is
    added when the *--clinfo* option is used.  A brief listing of key parameters is available
    with the *--short* command line option.  A simplified table of current GPU state is
    displayed with the *--table* option. The *--no_fan* can be used to ignore fan settings.  The
    *--pstate* option can be used to output the p-state table for each GPU instead of the list
    of basic parameters.  The *--ppm* option is used to output the table of available
    power/performance modes instead of basic parameters.  The *--features* option is used to output
    the table of amdgpu pp features and their status instead of basic parameters.  The *--force_all*
    results in an attempt to read all possible sensors, regardless of how the GPU is classified.  The
    *--raw* will read all possible driver files and display with indicators of if a gpu-util key word
    and description is associated with each file along with its contents.  The *--verbose* option
    will display progress and informational messages generated by the utilities.  By default,
    output data is formatted and color coded, so the *--no_markup* option can be specified
    to get plain text.

    Copyright (C) 2019  RicksLab

    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, see <https://www.gnu.org/licenses/>.
"""
__author__ = 'RueiKe'
__copyright__ = 'Copyright (C) 2019 RicksLab'
__license__ = 'GNU General Public License'
__program_name__ = 'gpu-ls'
__maintainer__ = 'RueiKe'
__docformat__ = 'reStructuredText'
# pylint: disable=multiple-statements
# pylint: disable=line-too-long
# pylint: disable=bad-continuation

import argparse
import sys
import logging
from GPUmodules import __version__, __status__, __credits__
from GPUmodules import GPUmodule as Gpu
from GPUmodules import env

LOGGER = logging.getLogger('gpu-utils')


def main() -> None:
    """
    Main flow for gpu-ls.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--about', help='README',
                        action='store_true', default=False)

    # Arguments affecting overall format.
    format_group = parser.add_mutually_exclusive_group(required=False)
    format_group.add_argument('--long', help='Long listing of GPU details. Includes ppm, pstate, and features.',
                              action='store_true', default=False)
    format_group.add_argument('--short', help='Short listing of basic GPU details',
                              action='store_true', default=False)
    format_group.add_argument('--table', help='Current status of readable GPUs',
                              action='store_true', default=False)
    format_group.add_argument('--raw', help='Show all raw GPU sensor data',
                              action='store_true', default=False)

    # Arguments to select detail reports.
    detail_group = parser.add_mutually_exclusive_group(required=False)
    detail_group.add_argument('--features', help='Output amdgpu Feature table instead of GPU details',
                              action='store_true', default=False)
    detail_group.add_argument('--pstates', help='Output pstate tables instead of GPU details',
                              action='store_true', default=False)
    detail_group.add_argument('--ppm', help='Output power/performance mode tables instead of GPU details',
                              action='store_true', default=False)
    detail_group.add_argument('--clinfo', help='Include openCL with card details',
                              action='store_true', default=False)

    # Arguments that influence report behavior.
    parser.add_argument('--verbose', help='Display informational message of GPU util progress',
                        action='store_true', default=False)
    parser.add_argument('--force_all', help='Force attempt to read all sensors',
                        action='store_true', default=False)
    parser.add_argument('--no_markup', help='Do not format ls output',
                        action='store_true', default=False)
    parser.add_argument('--no_fan', help='Do not include fan setting options',
                        action='store_true', default=False)
    parser.add_argument('-d', '--debug', help='Debug logger output',
                        action='store_true', default=False)
    args = parser.parse_args()

    # About me
    if args.about:
        print(__doc__)
        print('Author: ', __author__)
        print('Copyright: ', __copyright__)
        print('Credits: ', *['\n      {}'.format(item) for item in __credits__])
        print('License: ', __license__)
        print('Version: ', __version__)
        print('Install Type: ', env.GUT_CONST.install_type)
        print('Maintainer: ', __maintainer__)
        print('Status: ', __status__)
        sys.exit(0)

    if args.short: args.no_fan = True
    env.GUT_CONST.set_args(args, __program_name__)
    LOGGER.debug('########## %s %s', __program_name__, __version__)

    if env.GUT_CONST.check_env() < 0:
        print('Error in environment. Exiting...')
        sys.exit(-1)

    # Get list of GPUs and exit if no GPUs detected
    gpu_list = Gpu.GpuList()
    gpu_list.set_gpu_list(clinfo_flag=True)
    num_gpus = gpu_list.num_gpus()
    if num_gpus['total'] == 0:
        print('No GPUs detected, exiting...')
        sys.exit(-1)

    # Display vendor and driver details
    Gpu.print_driver_vendor_summary(gpu_list)

    # Read data static/dynamic/info/state driver information for GPUs
    gpu_list.read_gpu_sensor_set(data_type=Gpu.GpuItem.SensorSet.All)

    # Check number of readable/writable GPUs again
    Gpu.print_gpu_rw_summary(gpu_list)

    # If specified, display raw sensor details
    if args.raw:
        gpu_list.read_raw_sensors()
        gpu_list.print_raw()
        sys.exit(0)

    # Print out user requested details
    if args.long:
        gpu_list.print(long=args.long)
    elif args.short:
        gpu_list.print(short=args.short)
    elif args.table:
        com_gpu_list = Gpu.set_mon_plot_compatible_gpu_list(gpu_list)
        com_gpu_list.print_table(title='Status of Compatible GPUs:')
    elif args.pstates or args.ppm or args.features or args.clinfo:
        if args.pstates:
            gpu_list.read_gpu_pstates()
            gpu_list.print_param_table(param_name='pstate')
        elif args.ppm:
            gpu_list.print_param_table(param_name='ppm')
        elif args.features:
            gpu_list.print_param_table(param_name='pp_features')
        elif args.clinfo:
            gpu_list.print_param_table(param_name='clinfo')
        print('')
    else:
        gpu_list.print()

    sys.exit(0)


if __name__ == '__main__':
    main()
