/*
    zfile.c - file utilities
    Copyright (C) 2011-2012 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 <zfile.h>
#include <zstr.h>

#include <glib.h>

#include <string.h>

#ifdef Z_HAVE_WINSOCK2_H
#include <winsock2.h>
#endif

#ifdef Z_HAVE_WINDOWS_H
#include <windows.h>
#endif

#ifdef Z_HAVE_PSAPI_H
#include <psapi.h>
#endif

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

#ifdef Z_HAVE_STDLIB_H
#include <stdlib.h>
#endif


char *z_dirname(char *filename){
	char *c;

	if (!filename) return NULL;
	if (strlen(filename) == 0) return filename;
	
	for (c = filename + strlen(filename) - 1; c >= filename; c--)
	{
		if (*c != '/' && *c != '\\') continue;
		*c = '\0';
		return filename;
	}
	return filename + strlen(filename);	// empty string
}

const char *z_filename(const char *filename){
	const char *c;

	if (!filename) return NULL;
	if (strlen(filename) == 0) return filename;
	
	for (c = filename + strlen(filename) - 1; c >= filename; c--)
	{
		if (*c != '/' && *c != '\\') continue;
		return c + 1;
	}
	return filename;
}

const char *z_extension(const char *filename){
	const char *c, *f;

	f = z_filename(filename);
	if (!f) return NULL;

	c = strchr(filename, '.');
	if (c == NULL) return filename + strlen(filename);

	return c;
}

#ifdef Z_MSC_MINGW
char *z_wokna(char *file){
	char *c;

	for (c = file; *c != '\0'; c++) if (*c == '/') *c = '\\';
	return file;
}
#endif

char *z_unix(char *file){
	char *c;

	for (c = file; *c != '\0'; c++) if (*c == '\\') *c = '/';
	return file;
}




char *z_optimize_path(char *src){

    int first, last, i;
    gchar **items, *c;
    GString *gs;

    if (!src) return NULL;
    if (src[0]=='\0') return src;
	for (c = src; *c != '\0'; c++){
		if (*c == '\\') *c = '/';
	}

    if (strcmp(src, ".")==0) return src;
    if (strcmp(src, "./")==0) return src;
    
    first=src[0]=='/';
    last=src[0]&&src[strlen(src)-1]=='/';
    items=g_strsplit(src, "/", 0); 
    if (!items) return src;

    gs=g_string_sized_new(strlen(src));
    g_free(src);
    src=NULL;
    if (first) g_string_append_c(gs, '/');

    for (i=0; items[i]; i++){
        if (strcmp(items[i], ".")==0){
            continue;
        }
        if (items[i+1] && strcmp(items[i+1], "..")==0){
            i++;
            continue;
        }
        if (strlen(items[i])==0) continue;
        g_string_append(gs, items[i]);
        if (items[i+1]) g_string_append_c(gs, '/');
    }
    if (last && (!gs->str[0] || (gs->str[0] && gs->str[strlen(gs->str)-1]!='/'))) 
        g_string_append_c(gs, '/');

    c=g_strdup(gs->str);
    g_string_free(gs, TRUE);
    g_strfreev(items);
    return c;
}


char *z_binary_file_name(){
#ifdef Z_MSC_MINGW
    char path[_MAX_PATH + 1];

//	if (GetProcessImageFileName(GetCurrentProcess(), path, _MAX_PATH) == 0) return NULL;
	if (GetModuleFileName(NULL, path, _MAX_PATH) == 0) return NULL;
    return g_strdup(path);
#endif

#ifdef Z_UNIX
    char path[4096+1];
    int len;

    len = readlink("/proc/self/exe", path, 4096);
    if (len < 0) return NULL;
    path[len] = '\0';
    return g_strdup(path);
#endif

	return NULL;

}

char *z_libzia_file_name(void **codebase){
#ifdef Z_MSC_MINGW
	*codebase = NULL;
    return NULL;
#endif

#ifdef Z_UNIX
    FILE *f;
    char s[256], *ret = NULL;
//    char *tkp = getenv("TKP");

    f = fopen("/proc/self/maps", "rt");
    if (!f) return NULL;

//    if (tkp) printf("z_libzia_file_name opened /proc/self/maps\n");

    while (fgets(s, 255, f)){
        char *tok;
        char *c;
        s[255] = '\0';
        
        z_strip_crlf(s);
//        if (tkp) printf("s='%s'\n", s);


        char *base = strtok_r(s, " \t", &tok);
        char *flgs = strtok_r(NULL, " \t", &tok);
        if (!flgs) continue;
        if (strlen(flgs) < 4) continue;
        if (flgs[2] != 'x') continue;

        /*char *offs =*/ strtok_r(NULL, " \t", &tok);
        /*char *devi =*/ strtok_r(NULL, " \t", &tok);
        /*char *inod =*/ strtok_r(NULL, " \t", &tok);
        char *file = strtok_r(NULL, " \t", &tok);
//        if (tkp) printf("file='%s'\n", file);
        if (!file) continue;
        
        c = strstr(file, "libzia");
        if (!c) continue;


        ret = g_strdup(file);
//        if (tkp) printf("ret='%s'\n", ret);
        if (codebase) {
//            if (tkp) printf("base='%s'\n", base);
            *codebase = z_strtop(base);
//            if (tkp) printf("*codebase=%p\n", *codebase);
        }
        break;
    }


    fclose(f);
    return ret;
#endif
    return NULL;
}

