/*
 * YCKDeviceInfo.h
 *
 *  Created on: Jun 13, 2020
 *      Author: dengminhao@axzt.net
 */

#ifndef YCKSDWAN_YCKSDWAN_UTILS_YCKDEVICEINFO_H_
#define YCKSDWAN_YCKSDWAN_UTILS_YCKDEVICEINFO_H_
#include <string>
#include <vector>
#include <map>
#include <mutex>

#ifdef SDK_SIMPLE_INCLUDE
#include "common.h"
#include "NVVideoImageBuffer.h"
#else
#include <YCKSdwan/common.h>
#include <YCKit/Video/NVVideoImageBuffer.h>
#endif

struct DriverInfo {
	std::string name;	
	std::string date;	//install date
	std::string version;
};

class DLL_DECL_SDWAN YCKDeviceInfo{
public:

	virtual std::string platform();
	virtual std::string deviceName();
	virtual int cpu_core_number();
	virtual float mem_usage();
    virtual uint64_t mem_peak_usage();
    virtual std::string virtual_mem_info(bool refresh);
    inline uint64_t free_virtual_mem() { return free_virtual_mem_; }

	virtual void get_memory_info(uint64_t& avail_mem, uint64_t& total_mem);
	virtual void get_gpu_info(std::vector<std::string>& gpu_list);
    virtual void get_gpu_desc(std::vector<uint32_t>& gpu_ids, std::vector<std::string>& gpu_names,
        std::vector<std::string>& gpu_hwids, std::vector<std::string>& gpu_driver_versions,
        std::vector<bool>& gpu_driver_installed);
	virtual std::string get_os_version();
	virtual std::string get_os_name();
	virtual std::string get_ip_info();
	virtual std::string get_cpu_info();
    virtual std::string get_cpu_arch();
	virtual std::string get_app_version();
	virtual std::string get_sdk_version();
	virtual std::string get_screen_resolution();
    virtual float get_screen_scale_rate();

	virtual float cached_cpu_usage(bool refresh=true);
	virtual float cached_total_cpu_usage(bool refresh=true);

    virtual float cached_gpu_usage(bool refresh=true);
    virtual float cached_total_gpu_usage(bool refresh=true);

	virtual int get_os_bit();

	inline uint64_t mem_vitural_size() {return mem_vsize;}
	virtual bool isLowEndDevice();
	virtual void setForceLowEnd(bool forced);
	inline int isCPULimited() {return is_CPU_Limited;}
	virtual bool isLowVoltageDevice();

    virtual NVPixelFormat forceCameraPixFormat();
    virtual void setForceCameraPixFormat(NVPixelFormat format);

	virtual std::string get_device_id();

	// 第一次获取会卡2s左右，force强制再刷新一次
	virtual std::vector<DriverInfo> get_audio_driver_info(bool force = false);
	virtual std::vector<DriverInfo> get_camera_driver_info(bool force = false);

	//from 0~10. <6≈LowEnd
	virtual int deviceCPUPerformanceLevel();
	//from 0~10. <6≈LowEnd. Need setGpuCodecFeature first. (== Prepare device in callmgr)
	virtual int deviceGPUPerformanceLevel();
	//from 0~10. <6≈LowEnd. Depends on cpu && gpu level.( So it will change after setGpuCodecFeature)
	virtual int devicePerformanceLevel();
	/**
	* The limited total cpu usage. It may be larger than total_cpu_usage
	* Note: only available in windows and win ver >= 8.0. Using it when its value > 0
	*/
	inline float cached_total_cpu_time_usage() {return cpu_time_usage;}

	virtual ~YCKDeviceInfo()=default;

	static YCKDeviceInfo sharedInst;

	/**
	 * 程序使用的总CPU占用。用timly方式计算的CPU占用更符合CPU的繁忙程度（和剩余可利用量）。
	 * 而默认的utility CPU占用更符合在资源管理器上看到的百分比，适合给用户看
	 */
	inline float cached_total_cpu_usage_time_prefered() {return cpu_time_usage>0?cpu_time_usage:cached_total_cpu_usage();}

	//Called by videoengine. Don't call it in any other else.
	void setGpuCodecFeature(const int* const supprtArr,int len);

private:
	bool is_gpu(const std::string& gpu_info);
	virtual float cpu_usage();
	virtual float total_cpu_usage();
    virtual void calc_gpu_usage();
	int determinePerfLvl();
	void update_driver_info();

private:
	std::string platform_name;
	std::string device_name;
	int cpu_core_numbers = 0;
	float mem_ug = 0;
    uint64_t mem_peak_usage_ = 0;
    uint64_t mem_vsize = 0;
    std::string virtual_mem_info_;
    uint64_t free_virtual_mem_ = 0;

	uint64_t avail_mem;
	uint64_t total_mem;
	std::vector<std::string> gpu_list;
	std::string os_version;
	std::string os_name;
	std::string ip_info;
	std::string cpu_info;
    std::string cpu_arch;
	std::string app_version;
	std::string sdk_version;
	std::string device_Id;
	std::vector<DriverInfo> audio_driver_info;
	std::vector<DriverInfo> camera_driver_info;

	float cached_cpu_ug = 0;
	float cached_total_cpu_ug = 0;
    float cached_gpu_ug = 0;
    float cached_total_gpu_ug = 0;

	int lowEndDevice = -1;
	int is_CPU_Limited = -1;
	float cpu_time_usage = -1;
	bool low_voltage_device = false;

    NVPixelFormat camera_pixformat = NV_FMT_NONE;

    std::mutex mutex_;
};


#endif /* YCKSDWAN_YCKSDWAN_UTILS_YCKDEVICEINFO_H_ */
