/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
//                                                                          //
//  pfConsoleDirSrc Functions                                               //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

#include "pfConsoleDirSrc.h"

#include "hsExceptions.h"

#ifdef HS_BUILD_FOR_WIN32

#define WIN32_EXTRA_LEAN
#define WIN32_LEAN_AND_MEAN
#ifndef _WINDOWS_H_ // redundant include guard to minimize compile times
#define _WINDOWS_H_
#include <windows.h>
#endif // _WINDOWS_H_

#include <winbase.h>

#include <sstream>


//// ParseDirectory //////////////////////////////////////////////////////////

hsBool  pfConsoleDirSrc::ParseDirectory(const std::string& path, const std::string& mask /* = "*.*" */)
{
    wchar* wPath = hsStringToWString(path.c_str());
    wchar* wMask = hsStringToWString(mask.c_str());
    hsBool ret = ParseDirectory(wPath, wMask);
    delete [] wPath;
    delete [] wMask;
    return ret;
}

hsBool  pfConsoleDirSrc::ParseDirectory(const std::wstring& path, const std::wstring& mask /* = L"*.*" */)
{
    std::wstringstream  search;
    std::wstring        file;
    WIN32_FIND_DATAW    findInfo;
    HANDLE              handle;

    hsAssert( fEngine != nil, "Cannot do a dir execute without an engine!" );

    search << path << L"\\" << mask;
    handle = FindFirstFileW(search.str().c_str(), &findInfo);
    if (handle == INVALID_HANDLE_VALUE)
        return false;

    do
    {
        if (!( findInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
        {
            std::wstringstream fileAndPath;
            fileAndPath << path << L"\\" << findInfo.cFileName;
            if (AlreadyProcessedFile(path, findInfo.cFileName))
                continue;
            AddProcessedFile(path, findInfo.cFileName);
            if (!fEngine->ExecuteFile(fileAndPath.str().c_str()))
            {
                // Change the following line once we have a better way of reporting
                // errors in the parsing
                std::wstringstream error;
                std::wstringstream caption;
                wchar* errorMsg = hsStringToWString(fEngine->GetErrorMsg());
                wchar* errorLine = hsStringToWString(fEngine->GetLastErrorLine());

                caption << L"Error parsing " << findInfo.cFileName;
                error << errorMsg << L":\n\nCommand: '" << errorLine << L"'\n\nPress OK to continue parsing files.";

                hsMessageBox(error.str().c_str(), caption.str().c_str(), hsMessageBoxNormal);               
                
                delete [] errorMsg;
                delete [] errorLine;

                FindClose(handle);
                SetCheckProcessedFiles(true);
                return false;
            }
        }
    } while (FindNextFileW(handle, &findInfo) != 0);

    FindClose(handle);
    SetCheckProcessedFiles(true);
    return true;
}

#else

#error This needs to be implemented for this platform!!!!

#endif

void pfConsoleDirSrc::ResetProcessedFiles()
{
    int i;
    for(i=0;i<fProcessedFiles.size(); i++)
        delete fProcessedFiles[i];
    fProcessedFiles.clear();    
}

//
// note: this n^2 linear search should be replaced with something
// faster if we have lots of init files and turn on the checkProcessing option.
//
hsBool pfConsoleDirSrc::AlreadyProcessedFile(const std::wstring& path, const std::wstring& file)
{
    if (fCheckProcessedFiles)
    {
        int i;
        for(i=0; i<fProcessedFiles.size(); i++)
        {
            if (file == fProcessedFiles[i]->fFile && path == fProcessedFiles[i]->fPath)
                return true;
        }
    }
    return false;
}

void pfConsoleDirSrc::AddProcessedFile(const std::wstring& path, const std::wstring& file)
{
    fProcessedFiles.push_back(TRACKED_NEW FileName(path, file));    
}