#include "sdk_precomp.h"
#include <wx/confbase.h>
#include <wx/fileconf.h>
#include <wx/log.h>
#include <wx/intl.h>
#include "manager.h"
#include "projectmanager.h"
#include "messagemanager.h"
#include "cbproject.h"
#include "workspaceloader.h"
#include "tinyxml/tinyxml.h"

WorkspaceLoader::WorkspaceLoader()
    : m_pActiveProj(0L)
{
	//ctor
}

WorkspaceLoader::~WorkspaceLoader()
{
	//dtor
}

inline ProjectManager* GetpMan() { return Manager::Get()->GetProjectManager(); }
inline MessageManager* GetpMsg() { return Manager::Get()->GetMessageManager(); }

bool WorkspaceLoader::Open(const wxString& filename)
{
    TiXmlDocument doc(filename.mb_str());
    if (!doc.LoadFile())
        return false;

//    ProjectManager* pMan = Manager::Get()->GetProjectManager();
//    MessageManager* pMsg = Manager::Get()->GetMessageManager();

    if (!GetpMan() || !GetpMsg())
        return false;

    // BUG: Race condition. to be fixed by Rick.
    // If I click close AFTER pMan and pMsg are calculated,
    // I get a segfault.
    // I modified classes projectmanager and messagemanager,
    // so that when self==NULL, they do nothing
    // (constructors, destructors and static functions excempted from this)
    // This way, we'll use the *manager::Get() functions to check for nulls.

    TiXmlElement* root;
    TiXmlElement* wksp;
    TiXmlElement* proj;
    cbProject* loadedProject;
    wxString projectFilename;

    root = doc.FirstChildElement("CodeBlocks_workspace_file");
    if (!root)
    {
        // old tag
        root = doc.FirstChildElement("Code::Blocks_workspace_file");
        if (!root)
        {
            GetpMsg()->DebugLog(_("Not a valid Code::Blocks workspace file..."));
            return false;
        }
    }
    wksp = root->FirstChildElement("Workspace");
    if (!wksp)
    {
        GetpMsg()->DebugLog(_("No 'Workspace' element in file..."));
        return false;
    }

    m_Title = _U(wksp->Attribute("title")); // Conversion to unicode is automatic (see wxString::operator= )
    if (m_Title.IsEmpty())
        m_Title = _("Default workspace");

    proj = wksp->FirstChildElement("Project");
    if (!proj)
    {
        GetpMsg()->DebugLog(_("Workspace file contains no projects..."));
        return false;
    }

    while (proj)
    {
        if(Manager::isappShuttingDown() || !GetpMan() || !GetpMsg())
            return false;
        projectFilename = _U(proj->Attribute("filename"));
        if (projectFilename.IsEmpty())
        {
            GetpMsg()->DebugLog(_("'Project' node exists, but no filename?!?"));
            loadedProject = 0L;
        }
        else
        {
            wxFileName wfname(filename);
            wxFileName fname(projectFilename);
            fname.MakeAbsolute(wfname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
            loadedProject = GetpMan()->LoadProject(fname.GetFullPath());
        }
        if (loadedProject)
        {
            int active = 0;
            int ret = proj->QueryIntAttribute("active", &active);
            switch (ret)
            {
                case TIXML_SUCCESS:
                    if (active == 1)
                        m_pActiveProj = loadedProject;
                    break;
                case TIXML_WRONG_TYPE:
                    GetpMsg()->DebugLog(_("Error %s: %s"), doc.Value(), doc.ErrorDesc());
                    GetpMsg()->DebugLog(_("Wrong attribute type (expected 'int')"));
                    break;
                default:
                    break;
            }
        }
        proj = proj->NextSiblingElement();
    }

    if (m_pActiveProj)
        GetpMan()->SetProject(m_pActiveProj);

    return true;
}

bool WorkspaceLoader::Save(const wxString& title, const wxString& filename)
{
    wxString buffer;
    wxArrayString array;

    ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetProjects();

    buffer << _T("<?xml version=\"1.0\"?>") << _T("\n");
    buffer << _T("<!DOCTYPE CodeBlocks_workspace_file>") << _T("\n");
    buffer << _T("<CodeBlocks_workspace_file>") << _T("\n");
    buffer << _T("\t") << _T("<Workspace title=\"") << title << _T("\">") << _T("\n");

    for (unsigned int i = 0; i < arr->GetCount(); ++i)
    {
        cbProject* prj = arr->Item(i);

        wxFileName wfname(filename);
        wxFileName fname(prj->GetFilename());
        fname.MakeRelativeTo(wfname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));

        buffer << _T("\t\t") << _T("<Project filename=\"") << fname.GetFullPath() << _T("\"");
        if (prj == Manager::Get()->GetProjectManager()->GetActiveProject())
            buffer << _T(" active=\"1\"");
        buffer << _T("/>") << _T("\n");
    }

    buffer << _T("\t") << _T("</Workspace>") << _T("\n");
    buffer << _T("</CodeBlocks_workspace_file>") << _T("\n");

    wxFile file(filename, wxFile::write);
    return cbWrite(file,buffer);
}


syntax highlighted by Code2HTML, v. 0.9.1