// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "DFPlatform.h"

// This file contains functions that are applicable to Windows

#ifdef _WINDOWS

#include <windows.h>
#include <SDL_image.h>
#include <stdio.h>


static void DFErrorMsgSetWin32(char **errmsg, DWORD code)
{
    if (errmsg == NULL)
        return;

    char *lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL,
                  code,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPTSTR)&lpMsgBuf,
                  0, NULL);
    size_t len = strlen(lpMsgBuf);
    while ((len > 0) &&
           ((lpMsgBuf[len - 1] == '\n') ||
            (lpMsgBuf[len - 1] == '\r') ||
            (lpMsgBuf[len - 1] == '.')))
        len--;
    lpMsgBuf[len] = '\0';
    *errmsg = xstrdup(lpMsgBuf);
    LocalFree(lpMsgBuf);
}

HANDLE onceMutex = NULL;

static int testAndSet(int *var,int value,HANDLE lock)
{
    WaitForSingleObject(lock,INFINITE);
    int oldValue = *var;
    *var = value;
    ReleaseMutex(lock);
    return oldValue;
}

static BOOL CALLBACK initOnceMutex(PINIT_ONCE initOnce,PVOID Parameter,PVOID *Context)
{
    onceMutex = CreateMutex(NULL,FALSE,NULL);
    return TRUE;
}

void DFInitOnce(DFOnce *once, DFOnceFunction fun)
{
    static INIT_ONCE initOnce = INIT_ONCE_STATIC_INIT;
    InitOnceExecuteOnce(&initOnce,initOnceMutex,NULL,NULL);
    if (testAndSet(once,1,onceMutex) == 0)
        fun();
}

int DFMkdirIfAbsent(const char *path, char **errmsg)
{
    if (!CreateDirectory(path,NULL) && (GetLastError() != ERROR_ALREADY_EXISTS)) {
        DFErrorMsgSetWin32(errmsg,GetLastError());
        return 0;
    }
    return 1;
}

int DFAddDirContents(const char *absPath, const char *relPath, int recursive, DFDirEntryList ***list, char **errmsg)
{
    DFDirEntryList **listptr = *list;
    WIN32_FIND_DATA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    size_t patternLen = strlen(absPath) + 2;
    char *pattern = (char *)xmalloc(patternLen+1);
    snprintf(pattern,patternLen+1,"%s/*",absPath);
    hFind = FindFirstFile(pattern,&ffd);
    if (hFind == INVALID_HANDLE_VALUE) {
        DFErrorMsgSetWin32(errmsg,GetLastError());
        free(pattern);
        return 0;
    }

    int ok = 1;
    do {
        if (!strcmp(ffd.cFileName,".") || !strcmp(ffd.cFileName,".."))
            continue;

        size_t absSubPathLen = strlen(absPath) + 1 + strlen(ffd.cFileName);
        size_t relSubPathLen = strlen(relPath) + 1 + strlen(ffd.cFileName);

        char *absSubPath = (char *)xmalloc(absSubPathLen+1);
        char *relSubPath = (char *)xmalloc(relSubPathLen+1);

        snprintf(absSubPath,absSubPathLen+1,"%s/%s",absPath,ffd.cFileName);
        snprintf(relSubPath,relSubPathLen+1,"%s/%s",relPath,ffd.cFileName);

        char *entryName;
        if (relSubPath[0] == '/')
            entryName = &relSubPath[1];
        else
            entryName = relSubPath;

        *listptr = (DFDirEntryList *)xcalloc(1,sizeof(DFDirEntryList));
        (*listptr)->name = xstrdup(entryName);
        listptr = &(*listptr)->next;

        if (recursive && (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            ok = DFAddDirContents(absSubPath,relSubPath,recursive,&listptr,errmsg);

        free(absSubPath);
        free(relSubPath);
    } while (ok && (FindNextFile(hFind,&ffd) != 0));

    FindClose(hFind);
    free(pattern);
    *list = listptr;
    return ok;
}

int DFGetImageDimensions(const void *data, size_t len, const char *ext,
                         unsigned int *width, unsigned int *height, char **errmsg)
{
    SDL_Surface *image = IMG_Load_RW(SDL_RWFromMem((void *)data,(int)len),1);
    if (image == NULL) {
        if (errmsg != NULL)
            *errmsg = xstrdup(IMG_GetError());
        return 0;
    }

    *width = (unsigned int)image->w;
    *height = (unsigned int)image->h;
    SDL_FreeSurface(image);
    return 1;
}

#endif
