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

DWORD mydrives = 100;
char lpBuffer[100];


void GetLogicalDriveStringsMy(){
    printf("\nGetLogicalDriveStrings\n");
    DWORD test;
    int i;
    test = GetLogicalDriveStrings(mydrives, (LPWSTR)lpBuffer);
    if (test != 0) {
        printf("The logical drives of this machine are:\n");
        for(i=0;i<100;i++) printf("%c", lpBuffer[i]);
        printf("\n");
    } else printf("GetLogicalDriveStrings() is failed lor!!! Error code: %d\n", GetLastError());
}


void GetVolumeInformationMy(){
    printf("\nGetVolumeInformation\n");
    BOOL boolRValue;
    TCHAR wszVolumeName[MAX_PATH + 1];
    DWORD dwVolumeSerialNumber;
    DWORD dwFileSystemFlags;
    TCHAR wszSystemName[MAX_PATH + 1];
    boolRValue = GetVolumeInformation(
            "G:\\", //default to volume for current working directory
            wszVolumeName,
            MAX_PATH,
            &dwVolumeSerialNumber,
            NULL, //component max length
            &dwFileSystemFlags,
            wszSystemName,
            MAX_PATH
    );

    printf("Volume name: %s\n", wszVolumeName);
    printf("Volume serial number: %lu\n", dwVolumeSerialNumber);
    printf("File system type: %s\n", wszSystemName);

    printf("File system characteristics:\n");
    if(dwFileSystemFlags & FILE_SUPPORTS_ENCRYPTION){
        printf("The file system supports encryption.\n");
    } else {
        printf("The file system does not support encryption.\n");
    }
    if(dwFileSystemFlags & FILE_PERSISTENT_ACLS){
        printf("The volume preserves and enforces ACLs.\n");
    } else {
        printf("The volume does not preserve and enforce ACLs.\n");
    }
    if(dwFileSystemFlags & FILE_SUPPORTS_USN_JOURNAL){
        printf("The volume supports update sequence number journals.\n");
    } else {
        printf("The volume does not support update sequence number journals.\n");
    }
    if(dwFileSystemFlags & FILE_SUPPORTS_EXTENDED_ATTRIBUTES){
        printf("The volume supports extended attributes.\n");
    } else {
        printf("The volume does not support extended attributes.\n");
    }
}

void GetFileSizeMy(){
    printf("\nGetFileSize\n");
    HANDLE hFile;
    TCHAR *szFileName = _TEXT("C:\\Users\\kail_\\CLionProjects\\lab1\\myFile.txt");
    LARGE_INTEGER structLargeInt;
    hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, (DWORD) NULL, NULL);

    if(hFile == INVALID_HANDLE_VALUE) {
        printf("Error no. %lu\n", GetLastError());
        exit(EXIT_FAILURE);
    }
    else {
        GetFileSizeEx(hFile, &structLargeInt);
        printf("Size: %lld bytes.\n", structLargeInt.QuadPart);
    }
}

void FindNextFileMy(){
    printf("\nFindNextFile\n");
    WIN32_FIND_DATA structWin32;
    HANDLE hSearch = FindFirstFile(_T("C:\\*"), &structWin32);
    printf("FirstFile\n");
    _tprintf(_T("%s\n"), structWin32.cFileName);
    printf("\nNextFiles\n");

    while (FindNextFile(hSearch, &structWin32)) {
        _tprintf(_T("%s\n"), structWin32.cFileName);
    }
    if (GetLastError() == ERROR_NO_MORE_FILES) {
        printf("No more files...\n");
    }

    FindClose(hSearch);

}

void GetWindowsDirectoryMy() {
    printf("\nGetWindowsDirectory\n");
    GetWindowsDirectory(lpBuffer, MAX_PATH);
    printf("Windows Directory\n%s", lpBuffer);
}

void CompareFileTimeMy() {
    printf("\n\nCompareFileTime\n");
    TCHAR *szFirstName = _TEXT("C:\\Users\\kail_\\CLionProjects\\lab1\\myFile.txt");
    TCHAR *szSecondName = _TEXT("C:\\Users\\kail_\\CLionProjects\\lab1\\move\\mySecondFile.txt");
    HANDLE hFileFirst;
    HANDLE hFileSecond;
    hFileFirst = CreateFile(szFirstName, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, (DWORD) NULL, NULL);
    hFileSecond = CreateFile(szSecondName, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, (DWORD) NULL, NULL);
    struct _FILETIME *first;
    struct _FILETIME *second;
    GetFileTime(hFileFirst, first, NULL, NULL);
    GetFileTime(hFileSecond, second, NULL, NULL);
    int result = CompareFileTime(first, second);
    switch (result) {
        case -1: printf("First Older"); break;
        case 0: printf("Same"); break;
        case 1: printf("Second Older"); break;
    }
}

void SetLocalTimeMy() {
    printf("\n\nSetLocalTime\n");
    SYSTEMTIME time;
    GetLocalTime(&time);
    printf("Current Time: %02d.%02d.%d %02d:%02d\n", time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute);
    time.wDay = 11;
    time.wMonth = 6;
    printf("New Time: %02d.%02d.%d %02d:%02d\n", time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute);
    SetLocalTime(&time);
    GetLocalTime(&time);
    printf("New Current Time: %02d.%02d.%d %02d:%02d", time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute);
}

void SetFileAttributesMy(){
    printf("\n\nCopyFile\n");
    char *szSecondName = "C:\\Users\\kail_\\CLionProjects\\lab1\\copy\\myCopyFile.txt";
    SetFileAttributes(szSecondName, 2);
}

void CreateFileMy(){
    printf("\n\nCreateFile\n");
    char *szSecondName = "C:\\Users\\kail_\\CLionProjects\\lab1\\newFile.txt";
    CreateFile(szSecondName, GENERIC_READ, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,  0, NULL);
}

void CopyFileMy() {
    printf("\n\nCopyFile\n");
    char *szFirstName = "C:\\Users\\kail_\\CLionProjects\\lab1\\myFile.txt";
    char *szSecondName = "C:\\Users\\kail_\\CLionProjects\\lab1\\copy\\myCopyFile.txt";
    BOOL exist = FALSE;
    CopyFile(szFirstName, szSecondName, exist);
}

void MoveFileMy() {
    printf("\n\nMoveFile\n");
    char *szFirstName = "C:\\Users\\kail_\\CLionProjects\\lab1\\mySecondFile.txt";
    char *szSecondName = "C:\\Users\\kail_\\CLionProjects\\lab1\\move\\mySecondFile.txt";
    MoveFile(szFirstName, szSecondName);
}

int main() {

//    GetLogicalDriveStrings+, GetVolumeInformation+, GetFileSize+, FindNextFile+,
//    GetWindowsDirectory+, CompareFileTime+, SetLocalTime+, SetFileAttributes,
//    CreateFile+, CopyFile+, MoveFile+
    CopyFileMy();
    MoveFileMy();
    GetLogicalDriveStringsMy();
    GetVolumeInformationMy();
    GetFileSizeMy();
    FindNextFileMy();
    GetWindowsDirectoryMy();
    CompareFileTimeMy();
    SetLocalTimeMy();
    CreateFileMy();
    SetFileAttributesMy();
    return 0;
}