#!/usr/bin/env python3
""" 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 keyword 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__ = 'RicksLab'
__copyright__ = 'Copyright (C) 2019 RicksLab'
__license__ = 'GNU General Public License'
__program_name__ = 'gpu-ls'
__maintainer__ = 'RicksLab'
__docformat__ = 'reStructuredText'
# pylint: disable=multiple-statements
# pylint: disable=line-too-long
# pylint: disable=consider-using-f-string

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 pstate, ppm, features, and clinfo.',
                              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('--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('--features', help='Output amdgpu Feature table 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
    print(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
    gpu_list.read_gpu_pstates()
    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.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()
