
# include "android_io.h"

#if defined ANDROID
# include <android/log.h>
#endif
# include <stdio.h>
# include <string.h>


#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "emulate1", __VA_ARGS__))

/// FILES START

# define NFILES 100



typedef struct
{
    FILE * f;
    int opened;
    unsigned long long pos;
    unsigned long long len;
    char data[2*1024*1024];
    char mode;
} files_t;

files_t files[NFILES] = {0};

int io_open (char * dir, char * filename, int mode)
{
    char fullpath  [500];
    FILE * fil;
    char Mode;

	int s;


    if (dir && strlen (dir))
        sprintf(fullpath, "%s/%s", dir, filename);
    else
        sprintf(fullpath, "%s", filename);

   

	s = size(fullpath);

    switch (mode)
    {
        case O_RDONLY :
#if  defined _WIN32
			fil = fopen(fullpath, "rb");
#else
        fil = fopen(fullpath, "r");
#endif
        Mode = 'r';
        break;

		case O_WRONLY :		
#if  defined _WIN32
			fil = fopen(fullpath, "wb");
#else
			fil = fopen(fullpath, "w");
#endif
			Mode = 'w';
			break;

			case O_RDWR :
#if  defined _WIN32
			fil = fopen(fullpath, "rb+");
#else
			fil = fopen(fullpath, "r+");
#endif
			Mode = 'w';
			break;
	
	}    

    if (!fil)
        return -1;

    for (int i=0; i<NFILES; i++)
    {
        if (!files[i].opened)
        {
            files[i].opened = 1;
            files[i].f = fil;
            files[i].pos = 0;
            files[i].len = s;
            fread(files[i].data, 1, files[i].len, files[i].f);
			rewind(fil);
            files[i].mode = Mode;

           // LOGI("io_open %s <%d>", fullpath, i);

            return i;
        }
    }

    return -2;
}

int io_creat (char * dir, char * filename)
{
    char fullpath  [500];
    FILE * fil;

    if (dir && strlen (dir))
        sprintf(fullpath, "%s/%s", dir, filename);
    else
		sprintf(fullpath, "%s", filename);

   //LOGI("io_creat %s",  fullpath);

#if  defined _WIN32
	fil = fopen(fullpath, "wb");
#else
	fil = fopen(fullpath, "w");
#endif

   // LOGI("%d", fil);

	if (!fil)
		return -1;

    for (int i=0; i<NFILES; i++)
    {
        if (!files[i].opened)
        {
            files[i].opened = 1;
            files[i].f = fil;
            files[i].f = fil;
            files[i].pos = 0;
            files[i].len = 0;
            files[i].mode = 'w';
            return i;
        }
    }

    return -2;
}

long long io_read (int fd, char * buffer, long long size)
{
    int toread;

    if (files[fd].pos >= files[fd].len)
        toread = 0;
    else
    {
        if ((files[fd].pos + size) < files[fd].len)
            toread = size;
        else
            toread = files[fd].len - files[fd].pos;
    }


    memcpy(buffer, &files[fd].data[files[fd].pos], toread);
    files[fd].pos += toread;

    return (toread);
}

long long io_read (int fd, unsigned char * buffer, long long size)
{
    int toread;

    if (files[fd].pos >= files[fd].len)
        toread = 0;
    else
    {
        if ((files[fd].pos + size) < files[fd].len)
            toread = size;
        else
            toread = files[fd].len - files[fd].pos;
    }


    memcpy(buffer, &files[fd].data[files[fd].pos], toread);
    files[fd].pos += toread;

    return (toread);
}

long long io_write (int fd, char * buffer, long long size)
{
    memcpy(&files[fd].data[files[fd].pos], buffer, size);
    files[fd].pos += size;

    if (files[fd].pos>files[fd].len)
        files[fd].len = files[fd].pos;

    return (size);
}

long long io_write (int fd, unsigned char * buffer, long long size)
{
    memcpy(&files[fd].data[files[fd].pos], buffer, size);
    files[fd].pos += size;

    if (files[fd].pos>files[fd].len)
        files[fd].len = files[fd].pos;

    return (size);
}


long long size(char * f)
{
    FILE * fil;
    size_t size_r;

    fil = fopen(f, "r");
    if (!fil)
        return 0;

    fseek(fil, 0, SEEK_END);
    size_r = ftell(fil);

    fclose (fil);

    return size_r;
}

int FileExists(char * f)
{
    FILE * fil;

    fil = fopen(f, "r");
    if (!fil)
        return 0;

    fclose (fil);

    return 1;
}


void io_close (int fd)
{
	int rv;

    if (files[fd].mode == 'w')
    {
        rv = fwrite(files[fd].data, 1, files[fd].len, files[fd].f);
       // LOGI("%d %d", rv, files[fd].len);
    }

    fclose(files[fd].f);
    files[fd].opened = 0;

     //LOGI("io_close <%d>", fd);
}

long long io_lseek (int fd, long long pos, int mode)
{
    if (mode==SEEK_SET)
    {
        files[fd].pos = pos;
        return (files[fd].pos);
    }

    if (mode==SEEK_CUR)
    {
        files[fd].pos = files[fd].pos + pos;
        return (files[fd].pos);
    }

	if (mode==SEEK_END)
    {
        files[fd].pos = files[fd].len + pos;
        return (files[fd].pos);
    }

}


long long io_fgets(int fd, char* buffer, long long size) { fgets((char*)buffer, size, files[fd].f);                                                                                                                                                                                                                                                return 0; }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   int io_feof(int fd) { return (feof(files[fd].f)); }


/// FILES END



unsigned char lower(unsigned char str)
{
    if ((str >= 65) && (str <= 90))
        return (str + 32);

    return str;
}

int	io_strcasecmp(char *s1, char *s2)
{
    int n1 = strlen(s1);
    int n2 = strlen(s2);
    int i;

    if (n1 != n2)
        return 1;

    for (i = 0; i < n1; i++)
        if (lower(s1[i]) != lower(s2[i]))
            return 1;

    return 	0;
}


int io_strncasecmp(char *s1, char *s2, int n)
{
    int i;

    for (i = 0; i < n; i++)
        if (lower(s1[i]) != lower(s2[i]))
            return 1;

    return 	0;
}

#if defined ANDROID

unsigned int strlen(char * str)
{
    char *s;

    for (s = str; *s; ++s);
    return(s - str);
}

/*
void * memcpy(void *dest, const void * src, unsigned int n)
{
    char * dp = (char *)dest;
    char * sp = (char *) src;


    while (n--)
        *dp++ = *sp++;

    return dest;
}
*/

char * strncpy(char *s1, char *s2, int n)
{
    char *s = s1;


    while (n > 0 && *s2 != '\0')
    {
        *s++ = *s2++;
        --n;
    }

    while (n > 0)
    {
        *s++ = '\0';
        --n;
    }

    return s1;
}

char * strcpy(char *s1, char *s2)
{
    char *s = s1;
    while ((*s++ = *s2++) != 0)
        ;
    return (s1);
}

char * strcat(char *s, const char *append)
{
char *save = s;

for (; *s; ++s);
while (*s++ = *append++);
return(save);
}


void MessageBoxErr(char * aeerr)
{
    __android_log_print(ANDROID_LOG_INFO, "TAG",  "%s", aeerr);
}

#endif
