/*
    Misc functions
    Copyright (C) 2012-2020 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/


#include <zmisc.h>

#include <zandroid.h>
#include <zpng.h>
#include <zsdl.h>
#include <zstr.h>

#include <glib.h>

#include <math.h>

#ifdef Z_HAVE_SHLOBJ_H
#include <shlobj.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#ifdef Z_HAVE_UNISTD_H
#include <unistd.h>
#endif


#ifdef Z_MSC
#pragma warning(disable : 4996)
#endif


#ifdef Z_HAVE_TERMIOS_H
#include <termios.h>

#ifdef Z_CYGWIN 
void cfmakeraw(struct termios *t)
{
    t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
    t->c_oflag &= ~OPOST;
    t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
    t->c_cflag &= ~(CSIZE|PARENB);
    t->c_cflag |= CS8;
    t->c_cc[VMIN] = 1;
    t->c_cc[VTIME] = 0;
}
#endif
#endif


char *z_strdup_home(void){
#ifdef Z_MSC_MINGW
    char appdata[MAX_PATH];

    if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 1 /*SHGFP_TYPE_CURRENT*/, appdata) == S_OK){
        return g_strdup(appdata);
    }else{
        return g_strdup(".");
    }
#else
    return g_strdup(getenv("HOME"));
#endif
}

#ifdef Z_MINGW
int setenv(const char *name, const char *value, int overwrite){
	char buf[1024];
   	snprintf(buf, 1023, "%s=%s", name, value);
	buf[1023] = '\0';
	putenv(buf);
	return 0;
}
#endif

#ifdef Z_MSC
int setenv(const char *name, const char *value, int overwrite){
	_putenv_s(name, value);
	return 0;
}
#endif

char *z_username(char *buf, int buflen){
#ifdef Z_MSC_MINGW
	DWORD dw = buflen;
	if (!GetUserName(buf, &dw)){
		strcpy(buf, "");
	}
#else
	g_snprintf(buf, buflen, "%d", getuid());
#endif
	return buf;
}



#ifdef Z_UNIX_MINGW
#include "settings.c"
void z_get_settings(GString *gs){
	g_string_append(gs, z_settings);
}
#endif

#ifdef Z_ANDROID
void z_get_settings(GString *gs){
	SDL_version sdl_compiled;

	g_string_append_printf(gs, "------ Libzia settings: --------\n");
	g_string_append_printf(gs, "   version: %s %s\n", Z_PACKAGE, Z_VERSION);
	g_string_append_printf(gs, "  platform: %s\n", Z_PLATFORM);
    g_string_append_printf(gs, "  compiler: gcc %d.%d.%d ", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
	g_string_append_printf(gs, "     sizes: int=%d, long=%d, long long=%d, void*=%d\n", sizeof(int), sizeof(long), sizeof(long long), sizeof(void *));
	g_string_append_printf(gs, " endianity: little\n");
	g_string_append_printf(gs, "   libglib: yes %d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version);  
    g_string_append_printf(gs, "    libgtk: no\n");
	SDL_VERSION(&sdl_compiled);
	g_string_append_printf(gs, "    libsdl: yes %d.%d.%d\n", sdl_compiled.major, sdl_compiled.minor, sdl_compiled.patch);
#ifdef Z_HAVE_LIBPNG
	g_string_append_printf(gs, "    libpng: yes ");
	zpng_get_version(gs);
	g_string_append(gs, "\n");
#else
	g_string_append_printf(gs, "    libpng: no\n");
#endif
#ifdef Z_HAVE_LIBFTDI
	g_string_append_printf(gs, "   libftdi: yes 0.19\n");
#else
	g_string_append_printf(gs, "   libftdi: no\n");
#endif
	g_string_append_printf(gs, "    libbfd: no \n");
	g_string_append_printf(gs, "      opts:");
	g_string_append(gs, "\n");
	
}
#endif

#ifdef Z_MSC
void z_get_settings(GString *gs){
	SDL_version sdl_compiled;

	g_string_append_printf(gs, "------ Libzia settings: --------\n");
	g_string_append_printf(gs, "   version: static\n");//%s-%s %s\n", PACKAGE, Z_PLATFORM, VERSION);
	g_string_append_printf(gs, "  compiler: msvc %d.%02d\n", _MSC_VER / 100, _MSC_VER % 100);
	g_string_append_printf(gs, "     sizes: int=%d, long=%d, long long=%d, void*=%d\n", sizeof(int), sizeof(long), sizeof(long long), sizeof(void *));
	g_string_append_printf(gs, " endianity: little\n");
	g_string_append_printf(gs, "   libglib: yes %d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version);  
    g_string_append_printf(gs, "    libgtk: no\n");
#ifdef Z_HAVE_SDL
	SDL_VERSION(&sdl_compiled);
	g_string_append_printf(gs, "    libsdl: yes %d.%d.%d\n", sdl_compiled.major, sdl_compiled.minor, sdl_compiled.patch);
#else
	g_string_append_printf(gs, "    libsdl: no\n");
#endif
#ifdef Z_HAVE_LIBPNG
	g_string_append_printf(gs, "    libpng: yes ");
	zpng_get_version(gs);
	g_string_append(gs, "\n");
#else
	g_string_append_printf(gs, "    libpng: no\n");
#endif
#ifdef Z_HAVE_LIBFTDI
	g_string_append_printf(gs, "   libftdi: yes 1.4\n");
#else
	g_string_append_printf(gs, "   libftdi: no\n");
#endif
	g_string_append_printf(gs, "    libbfd: no \n");
	g_string_append_printf(gs, "      opts:");
#ifdef _MT
	g_string_append_printf(gs, " MULTITHREAD");
#endif
#ifdef _DLL
	g_string_append_printf(gs, " DLL");
#endif
#ifdef _DEBUG
	g_string_append_printf(gs, " DEBUG");
#endif
	g_string_append(gs, "\n");
	
}
#endif

double z_min3_d(double a, double b, double c)
{
    double min = a;
    if (b < min) min=b;
    if (c < min) min=c;
    return min;
}

double z_max3_d(double a, double b, double c)
{
    double max = a;
    if (b > max) max=b;
    if (c > max) max=c;
    return max;
}

#ifdef Z_MSC_MINGW
int zreg_getint(HKEY hSecKey, const char *section, const char *entry)
{
	HKEY hKey;
	DWORD dwValue;
	DWORD dwType;
	DWORD dwCount = sizeof(DWORD);
	int rc;
	LONG lResult;

	rc=RegOpenKeyEx(hSecKey, section, 0, KEY_READ, &hKey);
	if (rc != ERROR_SUCCESS){
		return -1;
	}

	lResult = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)&dwValue, &dwCount);
	RegCloseKey(hKey);
	if (lResult != ERROR_SUCCESS) return -1;
	if (dwType != REG_DWORD) return -1;
	if (dwCount != sizeof(dwValue)) return -1;
	return dwValue;
}

char *zreg_getstr(HKEY hSecKey, const char *section, const char *entry){
	DWORD dwType, dwCount;
	HKEY hKey;
	int rc;
	LONG lResult;
	char *strValue;

	rc=RegOpenKeyEx(hSecKey, section, 0, KEY_READ, &hKey);
	if (rc != ERROR_SUCCESS){
		return NULL;
	}

	
	lResult = RegQueryValueEx(hKey, entry, NULL, &dwType, NULL, &dwCount);
	if (lResult != ERROR_SUCCESS){
		RegCloseKey(hKey);
		return NULL;
	}

	if (dwType != REG_SZ){
		RegCloseKey(hKey);
		return NULL;
	}

	strValue = g_new0(char, dwCount + 1);
	lResult = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)strValue, &dwCount);
	
	if (lResult != ERROR_SUCCESS)
	{
		RegCloseKey(hKey);
		return NULL;
	}

	if (dwType != REG_SZ){
		return NULL;
	}
	return strValue;
}

#endif

#ifdef Z_MSC_MINGW
int z_browser(char *url){
	ShellExecute(NULL, "open", url, NULL, NULL, 0);
	return 0;
}
#endif

#ifdef Z_ANDROID
int z_browser(char *url){
	zandroid_browser(url);
	return 0;
}
#endif

#ifdef Z_UNIX
int z_browser(char *url){
    char *cmd;
    int ret;
   
    cmd = g_strconcat("xdg-open ", url, NULL);

    ret = system(cmd); 
    g_free(cmd);
    return ret;
}
#endif


#if _MSC_VER < 1700 /* 2012 */
double round(double number)
{
	return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
}
#endif

