#ifndef MINER_H
#define MINER_H

#include "config.h"

#include "algorithm.h"

#include <stdbool.h>
#include <stdint.h>
#include <sys/time.h>
#include <pthread.h>
#include <sched.h>

//#include "elist.h"
//#include "uthash.h"
//#include "logging.h"
//#include "util.h"
#include <sys/types.h>
#ifndef WIN32
# include <sys/socket.h>
# include <netdb.h>
#endif

#ifdef __APPLE_CC__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#ifdef HAVE_ALLOCA_H

/*
# include <alloca.h>
#elif defined __GNUC__
# ifndef WIN32
#  define alloca __builtin_alloca
# else
#  include <malloc.h>
# endif

*/

#include <malloc.h>



#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# ifndef HAVE_ALLOCA
#  ifdef  __cplusplus
extern "C"
#  endif
void *alloca (size_t);
# endif
#endif

#ifdef __MINGW32__
#include <windows.h>
#include <io.h>

//static inline int fsync (int fd)
//{/
//	return (FlushFileBuffers ((HANDLE) _get_osfhandle (fd))) ? 0 : -1;
//}


struct cgpu_info {
    cl_ulong max_alloc;
    cl_ulong cacheline_size;
};




	int sgminer_id;
//	struct device_drv *drv;
	int device_id;
	char *name;  /* GPU family codename. */
	char *device_path;
	void *device_data;

	enum dev_enable deven;
	int accepted;
	int rejected;
	int hw_errors;
	double rolling;
	double total_mhashes;
	double utility;
//	enum alive status;
	char init[40];
//	struct timeval last_message_tv;

	int threads;
//	struct thr_info **thr;

	int64_t max_hashes;

	char *kernelname;  /* Human-readable kernel name. */
	bool mapped;
	int virtual_gpu;
	int virtual_adl;

	int intensity;
	int xintensity;
	int rawintensity;
	bool dynamic;

	cl_uint vwidth;
	size_t work_size;
	cl_ulong max_alloc;
	cl_ulong cacheline_size;
//	algorithm_t algorithm;

	int opt_lg, lookup_gap;
	size_t opt_tc, thread_concurrency;
	size_t shaders;
//	struct timeval tv_gpustart;
	int intervals;

	bool new_work;

	float temp;
	int cutofftemp;

#ifdef HAVE_ADL
	bool has_adl;
	struct gpu_adl adl;

	int gpu_engine;
	int min_engine;
	int gpu_fan;
	int min_fan;
	int gpu_memclock;
	int gpu_memdiff;
	int gpu_powertune;
	float gpu_vddc;
#endif
	int diff1;
	double diff_accepted;
	double diff_rejected;
	int last_share_pool;
//	time_t last_share_pool_time;
//	double last_share_diff;
//	time_t last_device_valid_work;

//	time_t device_last_well;
//	time_t device_last_not_well;
//	enum dev_reason device_not_well_reason;
	int thread_fail_init_count;
	int thread_zero_hash_count;
	int thread_fail_queue_count;
	int dev_sick_idle_60_count;
	int dev_dead_idle_600_count;
	int dev_nostart_count;
	int dev_over_heat_count;	// It's a warning but worth knowing
	int dev_thermal_cutoff_count;
	int dev_comms_error_count;
	int dev_throttle_count;

//	struct sgminer_stats sgminer_stats;

//	pthread_rwlock_t qlock;
//	struct work *queued_work;
//	struct work *unqueued_work;
	unsigned int queued_count;

	bool shutdown;

//	struct timeval dev_start_tv;
};

//extern bool add_cgpu(struct cgpu_info*);


struct thr_info {
	int		id;
	int		device_thread;

	pthread_t	pth;
	cgsem_t		sem;
	struct thread_q	*q;
	struct cgpu_info *cgpu;
	void *cgpu_data;
	struct timeval last;
	struct timeval sick;

	bool	pause;
	bool	paused;
	bool	getwork;
	double	rolling;

	bool	work_restart;
	bool	work_update;
};

#endif