// filesystem.cc
//
// Project: Ampache Browser
// License: GNU GPLv3
//
// Copyright (C) 2015 - 2024 Róbert Čerňanský



#ifdef _WIN32
#include <windows.h>
#else
#include <dirent.h>
#include <cstdio>
#endif

#include <sys/stat.h>
#include <cerrno>
#include <string>
#include "infrastructure/filesystem.h"



namespace infrastructure {

// mode is not used on Windows
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
bool Filesystem::makePath(const std::string& path, unsigned int mode) {
#pragma GCC diagnostic pop
    auto mkdirResult = MKDIR(path.c_str(), mode);
    if (mkdirResult == 0) {
        return true;
    }

    if (errno == ENOENT) {
        if (makePath(path.substr(0, path.find_last_of(PATH_SEP)))) {
            return MKDIR(path.c_str(), mode) == 0;
        }
    }

    return false;
}



bool Filesystem::isDirExisting(const std::string& path) {
#ifdef _WIN32
    struct _stat dirStat;
    int statResult = _wstat(StringEncoding::utf8ToWide(path).c_str(), &dirStat);
#else
    struct stat dirStat;
    int statResult = stat(path.c_str(), &dirStat);
#endif
    return statResult == 0 && dirStat.st_mode & S_IFDIR;
}



bool Filesystem::removeAllFiles(const std::string& path) {
#ifdef _WIN32
    std::wstring pathW = StringEncoding::utf8ToWide(path);

    WIN32_FIND_DATAW findData;
    HANDLE findHandle = FindFirstFileW((pathW + L"*").c_str(), &findData);
    if (findHandle == INVALID_HANDLE_VALUE) {
        return false;
    }

    do {
        std::wstring fileName = findData.cFileName;
        if (fileName != L"." && fileName != L"..") {
            std::wstring filePath = pathW + fileName;
            SetFileAttributesW(filePath.c_str(), FILE_ATTRIBUTE_NORMAL);
            DeleteFileW(filePath.c_str());
        }
    } while (FindNextFileW(findHandle, &findData) == TRUE);
    FindClose(findHandle);
#else
    auto dir = opendir(path.c_str());
    if (dir == nullptr) {
        return false;
    }

    dirent* file;
    while ((file = readdir(dir)) != nullptr) {
        std::string fileName{file->d_name};
        if (fileName != "." && fileName != "..") {
            remove((path + fileName).c_str());
        }
    }
    closedir(dir);
#endif

    return true;
}

}
