/* 
   Name: IsAlreadyInstalled() (function)
   Author: Kip Warner
   Description: Checks to see if a given packages is already installed for dev...
   Copyright: Yes
*/

#include "prototypes.h"

    // Directory where vUpdate is...
    extern char    g_szExeDirectory[256];
    
    // Directory of temp folder...
    extern char    g_szTempDirectory[256];
    
    // Guess...
    extern char    g_szAppName[32];
    
    // Debug mode...
    extern BOOL    g_bDebugMode;

// Checks to see if a given package is already installed on the system...
BOOL IsAlreadyInstalled(Package package, HWND hStatus)
{
    // Variables...
    char                szLine[128];
    char                szOldPath[256];
    FILE               *hInstallDatabase                = NULL;
    char               *pszString                       = NULL;
    char                szLatestVersionInstalled[64]    = "0.0";
    
    // Remember the current directory...
    GetCurrentDirectory(sizeof(szOldPath)/sizeof(char), szOldPath);
    
    // Get into our root directory...
    SetCurrentDirectory(g_szExeDirectory);
    
    // Try to open install database...
    hInstallDatabase = fopen("vUpdate Install Database.txt", "r");
    
        // No install database...
        if(!hInstallDatabase)
        {
            // Create database...
            hInstallDatabase = fopen("vUpdate Install Database.txt", "w");
            
            // Still can't create...
            if(!hInstallDatabase)
            {
                StatusOut("Error: Cannot access install database...", hStatus);
                
                // Reset directory...
                SetCurrentDirectory(szOldPath);
                
                // Don't risk it...
                return PACKAGE_INSTALLED;
            }
            
            // Insert database header, because it is new...
            fprintf(hInstallDatabase, "# This file is generated by vUpdate and is used to keep\n"
                                      "# track of what has already been installed. It is highly\n"
                                      "# recommend that you don't edit its contents unless you\n"
                                      "# know what you are doing. Doing so can result in\n"
                                      "# either yourself or vUpdate going mad.\n");

            // Reset directory...
            SetCurrentDirectory(szOldPath);

            // No database means that there could not have been installs yet...
            fclose(hInstallDatabase);
            return PACKAGE_NOT_INSTALLED;
        }

    // Scan line by line and check if script version is newer...
    strcpy(szLatestVersionInstalled, "0.0");
    while(fgets(szLine, 256, hInstallDatabase))
    {
        // Replace new line char wtih null byte...
        pszString = strstr(szLine, "\n");
        if(pszString)
            *pszString = '\x0';

        // Found entry code, jot down version number if it is higher than the last one found...
        if(strcmp(szLine, package.szEntryCode) == 0)
        {
            // Get next line containing version string...
            fgets(szLine, 256, hInstallDatabase);

            // Replace new line char wtih null byte...
            pszString = strstr(szLine, "\n");
            if(pszString)
                *pszString = '\x0';

            // Copy over last one found if it is higher....
            if((double) atof(szLine) > (double) atof(szLatestVersionInstalled))
                strcpy(szLatestVersionInstalled, szLine);
        }
    }
    
    // We have scanned through entire file decide what to do...

        // Reset directory...
        SetCurrentDirectory(szOldPath);
        
        // Close database...
        fclose(hInstallDatabase);
        
        // Did not find any occurences...
        if(strcmp(szLatestVersionInstalled, "0.0") == 0)
            return PACKAGE_NOT_INSTALLED;
        
        // Last version found in database is older than in script...
        if((double) atof(package.szVersion) > (double) atof(szLatestVersionInstalled))
            return PACKAGE_NOT_INSTALLED;
        
        // Script contains older version, or already installed...
        if((double) atof(package.szVersion) <= (double) atof(szLatestVersionInstalled))
            return PACKAGE_INSTALLED;
}

// Logs an installation of pszEntryCode in the database...
BOOL LogInstallation(Package package, HWND hStatus)
{
    // Variables...
    char    szOldPath[256];
    FILE    *hInstallDatabase   = NULL;
    char    *pszFile            = NULL;
    char    szBuffer[256];
    int     nFileSize           = 0;
    BOOL    bUpdatedVersion     = FALSE;
    char    szTemp[256];
    char    *pszTemp            = NULL;
    char    szDebug[256];

    sprintf(szDebug, "Logging %s installation...", package.szEntryCode);
    DebugOut(szDebug);

    // Remember the current directory...
    GetCurrentDirectory(sizeof(szOldPath)/sizeof(char), szOldPath);
    
    // Get into our root directory...
    SetCurrentDirectory(g_szExeDirectory);
    
    // Try to open install database...
    hInstallDatabase = fopen("vUpdate Install Database.txt", "r");
    
        // Unable to open...
        if(!hInstallDatabase)
        {
            DebugOut("Couldn't open install database in read mode...");

            // Reset path...
            SetCurrentDirectory(szOldPath);
            return FALSE;
        }

    // How big is the file?...
    DebugOut("Getting file size...");
    fseek(hInstallDatabase, 0, SEEK_END);
    nFileSize = ftell(hInstallDatabase);
    
        // Reset seek head...
        fseek(hInstallDatabase, 0, SEEK_SET);
        
    sprintf(szDebug, "File size is %i bytes...\n] Allocating...\n", nFileSize);
    DebugOut(szDebug);

    // Allocate storage for file, and add a bit more...
    pszFile = (char *) malloc(nFileSize + 1024);
    
        // Can't allocate...
        if(!pszFile)
        {
            DebugOut("Failed to allocate enough memory to store file...");
            fclose(hInstallDatabase);
            return FALSE;
        }
        
    // Grab file...
    DebugOut("Reading file...");
    *pszFile = '\x0';
    while(fgets(szBuffer, 256, hInstallDatabase))
    {
        // This line contain an entry code of what we are already logging
        // Overwrite its version with our new one...

            // Remove new line char...
            strcpy(szTemp, szBuffer);
            pszTemp = strstr(szTemp, "\n");
            if(pszTemp) *pszTemp = '\x0';

        if(strcmp(szTemp, package.szEntryCode) == 0)
        {
            DebugOut("Found previous installation...");
            strcat(pszFile, szBuffer);
            fgets(szBuffer, 256, hInstallDatabase);
            strcpy(szBuffer, package.szVersion);
            strcat(szBuffer, "\n");
            bUpdatedVersion = TRUE;
        }

        // Append this line into memory...
        strcat(pszFile, szBuffer);
    }
    
    // Close stream...
    fclose(hInstallDatabase);
    
    // We already updated version in memory, write to disk...
    if(bUpdatedVersion)
    {
        DebugOut("Updated version...");

        // Open now in write mode...
        hInstallDatabase = fopen("vUpdate Install Database.txt", "w");
        
            // Can't open...
            if(!hInstallDatabase)
            {
                DebugOut("Can't open installation database for write...");
                free(pszFile);
                return FALSE;
            }
        
        // Rewrite new data...
        fputs(pszFile, hInstallDatabase);
    }

    // We didn't update version cause this is a totaly new entry, just append then...
    else
    {
        DebugOut("Added new entry...");

        // Open now in write mode...
        hInstallDatabase = fopen("vUpdate Install Database.txt", "a");
        
            // Can't open...
            if(!hInstallDatabase)
            {
                puts("] Can't open file for append...");
                free(pszFile);
                return FALSE;
            }

        // All good so far, log entry...
        fprintf(hInstallDatabase, "\n\n# %s installed by vUpdate %s on %s%s\n%s", 
                package.szTitle, 
                VUPDATE_VERSION_CHAR,
                getTimeDate(), 
                package.szEntryCode, 
                package.szVersion);
    }
    
    // Reset path...
    SetCurrentDirectory(szOldPath);
    
    // All good, close database...
    fclose(hInstallDatabase);
    free(pszFile);
    DebugOut("Logged successfully...");
    return TRUE;
}
