#!/usr/bin/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.

    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'
__credits__ = ['Craig Echt - Testing, Debug, Verification, and Documentation',
               'Keith Myers - Testing, Debug, Verification of NV Capability']
__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__
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)
    parser.add_argument('--short', help='Short listing of basic GPU details',
                        action='store_true', default=False)
    parser.add_argument('--table', help='Current status of readable GPUs',
                        action='store_true', default=False)
    parser.add_argument('--pstates', help='Output pstate tables instead of GPU details',
                        action='store_true', default=False)
    parser.add_argument('--ppm', help='Output power/performance mode tables instead of GPU details',
                        action='store_true', default=False)
    parser.add_argument('--clinfo', help='Include openCL with card details',
                        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)
    LOGGER.debug('########## %s %s', __program_name__, __version__)

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

    if (args.pstates or args.ppm) and args.table:
        print('The --table option can not be used with --pstate or --ppm, ignoring --table')

    # Get list of GPUs and get basic non-driver details
    gpu_list = Gpu.GpuList()
    gpu_list.set_gpu_list(clinfo_flag=True)

    # Check list of GPUs
    num_gpus = gpu_list.num_vendor_gpus()
    print('Detected GPUs: ', end='')
    for i, (type_name, type_value) in enumerate(num_gpus.items()):
        if i:
            print(', {}: {}'.format(type_name, type_value), end='')
        else:
            print('{}: {}'.format(type_name, type_value), end='')
    print('')
    if 'AMD' in num_gpus.keys():
        env.GUT_CONST.read_amd_driver_version()
        print('AMD: {}'.format(gpu_list.wattman_status()))
    if 'NV' in num_gpus.keys():
        print('nvidia smi: [{}]'.format(env.GUT_CONST.cmd_nvidia_smi))

    num_gpus = gpu_list.num_gpus()
    if num_gpus['total'] == 0:
        print('No GPUs detected, exiting...')
        sys.exit(-1)

    # 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
    num_gpus = gpu_list.num_gpus()
    print('{} total GPUs, {} rw, {} r-only, {} w-only\n'.format(num_gpus['total'], num_gpus['rw'],
                                                                num_gpus['r-only'], num_gpus['w-only']))

    # Read report specific details
    if args.clinfo:
        if not gpu_list.read_gpu_opencl_data():
            args.clinfo = False

    # Print out user requested details
    gpu_list.read_gpu_pstates()
    if args.pstates:
        gpu_list.print_pstates()
    if args.ppm:
        gpu_list.read_gpu_ppm_table()
        gpu_list.print_ppm_table()
    if not args.pstates and not args.ppm:
        if args.table:
            com_gpu_list = gpu_list.list_gpus(compatibility=Gpu.GpuItem.GPU_Comp.Readable)
            com_gpu_list.print_table(title='Status of Readable GPUs:')
        else:
            gpu_list.print(short=args.short, clflag=args.clinfo)
    sys.exit(0)


if __name__ == '__main__':
    main()
