/*  
    util.c

    Copyright (C) 2010-2019 Amf

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <libintl.h>
#include <locale.h>

#ifdef __WIN32__
#include "windows.h"
#include "shlobj.h"
#endif

#include "chroma.h"
#include "level.h"
#include "menu.h"
#include "display.h"
#include "util.h"

void display_quit();

void file_readline(FILE *file, char *buffer, size_t size)
{
    char c;
    size_t pos = 0;
    int ok = 1;

    while(ok)
    {
        c=fgetc(file);
        if(!feof(file) && c!=13 && c!=10 && c!=0 && pos<(size-1))
            buffer[pos++]=c; 
        else
            ok=0; 
    }
    buffer[pos]=0;
}

int isfile(char *filename)
{
    struct stat fst;

    if(stat(filename, &fst) == -1)
        return 0;

    if(S_ISREG(fst.st_mode))
        return 1;
      
      return 0;
}

int isdirectory(char *filename)
{
    struct stat fst;

    if(stat(filename, &fst) == -1)
        return 0;

    if(S_ISDIR(fst.st_mode))
        return 1;

    return 0;
}

void ensuredirectory(char *directory)
{
    char buffer[FILENAME_MAX + 4096];
    if(isdirectory(directory))
        return;

    errno = 0;
#ifdef __WIN32__
    if(mkdir(directory) && errno != EEXIST)
#else
    if(mkdir(directory, 0755) && errno != EEXIST)
#endif
    {
        sprintf(buffer, gettext("Unable to create directory '%s': %s"), directory, strerror(errno));
        warning(buffer);
    }
}

void getfilename(char *filename, char *fullfilename, int create, int location)
{
    char base[FILENAME_MAX];

#ifdef __WIN32__
#ifndef CSIDL_FLAG_CREATE
#define CSIDL_FLAG_CREATE 0x8000
#endif

#ifndef CSIDL_PERSONAL 
#define CSIDL_PERSONAL 0x05
#endif

#ifndef CSIDL_APPDATA
#define CSIDL_APPDATA 0x1A
#endif

#ifndef SHGFP_TYPE_CURRENT
#define SHGFP_TYPE_CURRENT 0
#endif

    typedef HRESULT (WINAPI *SHGETFOLDERPATH)(HWND, int, HANDLE, DWORD, LPTSTR);

    HINSTANCE shfolder_dll;
    SHGETFOLDERPATH SHGetFolderPath ;
#endif

    if(location == LOCATION_SYSTEM)
    {
#ifdef CHROMA_DATA_DIR
#ifndef __WIN32__
        sprintf(fullfilename, "%s%s", CHROMA_DATA_DIR, filename);
#else
    strcpy(fullfilename, filename);
#endif
#else
    strcpy(fullfilename, filename);
#endif
    return;
    }

    if(location == LOCATION_DOCUMENTS)
    {
#ifdef __WIN32__
        if((shfolder_dll = LoadLibrary("shfolder.dll")) != NULL)
        {
            SHGetFolderPath = (void *)GetProcAddress(shfolder_dll, "SHGetFolderPathA");
            if(SHGetFolderPath != NULL)
            {

                if(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, base) != S_OK)
                    strcpy(base, ".");
            }
            FreeLibrary(shfolder_dll);

            if(create)
                ensuredirectory(base);
        }
#endif

#ifndef __WIN32__
        if(getenv("HOME") != NULL)
        {
            snprintf(base, FILENAME_MAX, "%s", getenv("HOME"));
        base[FILENAME_MAX - 1] = 0;

            if(create)
            ensuredirectory(base);
        }
        else
        {
        strcpy(base, ".");
        }
#endif

        snprintf(fullfilename, FILENAME_MAX, "%s/%s", base, filename);
        fullfilename[FILENAME_MAX - 1] = 0;

        if(create)
        ensuredirectory(fullfilename);
    }

    if(location == LOCATION_LOCAL)
    {
#ifdef __WIN32__
        if((shfolder_dll = LoadLibrary("shfolder.dll")) != NULL)
        {
            SHGetFolderPath = (void *)GetProcAddress(shfolder_dll, "SHGetFolderPathA");
            if(SHGetFolderPath != NULL)
            {

                if(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, base) == S_OK)
                    strcat(base, "\\chroma");
                else
                    strcpy(base, "chroma");
            }
            FreeLibrary(shfolder_dll);

            if(create)
                ensuredirectory(base);
        }
#endif

#ifndef __WIN32__
        if(getenv("HOME") != NULL)
        {
            snprintf(base, FILENAME_MAX, "%s/.chroma", getenv("HOME"));
        base[FILENAME_MAX - 1] = 0;

            if(create)
            ensuredirectory(base);
        }
        else
        {
        strcpy(base, ".chroma");
        }
#endif

        snprintf(fullfilename, FILENAME_MAX, "%s/%s", base, filename);
        fullfilename[FILENAME_MAX - 1] = 0;

        if(strcmp(filename, "curses.chroma") == 0)
        create = 0;
        if(strcmp(filename, "sdl.chroma") == 0)
        create = 0;

        if(create)
        ensuredirectory(fullfilename);
    }
}

void warning(char *error)
{
#ifdef __WIN32__
    if(display_type() == DISPLAY_SDL)
        MessageBox(0,error,"Chroma",MB_OK);
    else
    {
        fprintf(stderr, "chroma: %s\n", error);
        sleep(5);
    }
#else
    fprintf(stderr, "chroma: %s\n", error);
#endif
}

void fatal(char *error)
{
    display_quit();
#ifdef __WIN32__
    if(display_type() == DISPLAY_SDL)
        MessageBox(0,error,"Chroma",MB_OK);
    else
    {
        fprintf(stderr, "chroma: %s\n", error);
        sleep(5);
    }
#else
    fprintf(stderr, "chroma: %s\n", error);
#endif

    exit(1);
}

int utf8strlen(char *string)
{
    int i, j;

    i = 0; j = 0;
    while(string[i])
    {
        if((string[i] & 0xc0) != 0x80)
            j ++;
        i++;
    }

    return j;
}

void utf8strncpy(char *out, char *in, int l)
{
    int i, x;

    i = 0; x = 0;
    while(in[i] != 0 && x < l)
    {
        out[i] = in[i];
        if((out[i] & 0xc0) != 0x80)
            x ++;
        i ++;
    }
    while(in[i] != 0 && (in[i] & 0xc0) == 0x80)
    {
        out[i] = in[i];
        i ++;
    }
    out[i] = 0; /* unlike the real strncpy! */
}
