/////////////////////////////////////////////////////////////////////////////
// Name:        packageutils.cpp
// Purpose:     wxPackageDataWithRef, wxPackageId, wxPackageIdArray,
//              wxPackageCondition
// Author:      Francesco Montorsi
// Modified by:
// Created:     2006-11-07
// RCS-ID:      $Id: packageutils.cpp,v 1.5 2007/01/28 14:35:29 frm Exp $
// Copyright:   (c) Francesco Montorsi
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////


// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

// includes
#include <wx/fileconf.h>
#include <wx/filename.h>
#include <wx/zipstrm.h>
#include <wx/wfstream.h>
#include <wx/ptr_scpd.h>
#include <wx/dir.h>

#include "wxp/package.h"
#include "wxp/wxp.h"
#include "wxp/wxbuild.h"


// wx array implementations
#include <wx/arrimpl.cpp> // this is a magic incantation which must be done!
WX_DEFINE_OBJARRAY(wxPackageDataWithRefArray);
WX_DEFINE_OBJARRAY(wxPackageIdArrayHelper);

// global objects
wxPackageDataWithRef wxEmptyPackageDataWithRef;
wxPackageId wxEmptyPackageId;
wxPackageIdArray wxEmptyPackageIdArray;
wxPackageCondition wxEmptyPackageCondition;
wxPackageHTMLOutputFormat wxEmptyPackageHTMLOutputFormat;


// ----------------------------------------------------------------------------
// string2enum helpers
// ----------------------------------------------------------------------------

wxString wxPackageSubstituteInfoContextName[] =
{
    _("wxhtml"),
    _("xhtml")
};

wxIMPLEMENT_STRING2ENUM(PackageSubstituteInfoContext, wxPSIC_MAX)


// ----------------------------------------------------------------------------
// wxPackageDataWithRef
// ----------------------------------------------------------------------------

void wxPackageDataWithRef::ExpandLocalRef(const wxString &path)
{
    if (m_strLocalRef.IsEmpty())
        return;       // no reference to expand!
    wxFileName fn;
    if (m_strLocalRef.Contains(wxT('#')))
        fn = m_strLocalRef.AfterFirst(wxT('#')).AfterFirst(wxT(':'));
    else
        fn = wxFileSystem::URLToFileName(m_strLocalRef);

    fn.MakeAbsolute(path);
    SetLocalRef(fn.GetFullPath());
}

void wxPackageDataWithRef::ExpandLocalRefToWXZRef(const wxString &wxzpath)
{
    if (m_strLocalRef.IsEmpty())
        return;       // no reference to expand!

    // the file: protocol is already added by this function!
    wxASSERT(!wxzpath.StartsWith(wxT("file:")));

    wxFileName fn(wxFileSystem::URLToFileName(m_strLocalRef));
    wxFileName wxz(wxzpath);

    // the path to the given WXZ should be an absolute path!
    wxASSERT(!wxz.IsDir() && wxz.IsAbsolute());

    // NB: after the "wxz:" protocol we still need forward slashes since
    //     we are building an URL !
    SetLocalRef(wxFileSystem::FileNameToURL(wxz) +
            wxT("#wxz:") + fn.GetFullPath(wxPATH_UNIX));
}


// ----------------------------------------------------------------------------
// wxPackageCondition
// ----------------------------------------------------------------------------

bool wxPackageCondition::IsValidForPackage(const wxPackage &pkg) const
{
    return IsValidForCurrentPlatform() &&
            IsValidForCompiler(pkg.GetCompilerSettings().GetSelFormat()) &&
            IsValidForBuildSys(pkg.GetBuildSystemType());
}

void wxPackageCondition::SetAlwaysTrue()
{
    m_buildSys = wxGetFullPackageBuildSystemTypeList();
    m_format = wxGetFullPackageCompilerFormatList();
    m_platform = wxGetFullPortIdList();
    m_stages = wxGetFullPackageBuildSystemStageList();
}

bool wxPackageCondition::operator==(const wxPackageCondition &cond) const
{
    return m_platform == cond.m_platform &&
            m_format == cond.m_format &&
            m_buildSys == cond.m_buildSys &&
            m_stages == cond.m_stages;
}



// ----------------------------------------------------------------------------
// wxPackageHTMLOutputFormatXMLDescriptor: helper class for wxPackageHTMLOutputFormat
// ----------------------------------------------------------------------------

class wxPackageHTMLOutputFormatXMLDescriptor : public wxXmlDocument
{
public:
    wxPackageHTMLOutputFormatXMLDescriptor() {}

    bool Load(const wxString &file, wxPackageHTMLOutputFormat *out)
    {
        if (!wxXmlDocument::Load(file))
            return false;

        if (GetRoot()->GetName() != wxT("wxpackage-viewformat"))
            return false;

        wxXmlNode *child = GetRoot()->GetChildren();
        while (child)
        {
            if (child->GetName() == wxT("name"))
            {
                out->m_strName = child->GetNodeContent();
            }
            else if (child->GetName() == wxT("description"))
            {
                out->m_strDescription = child->GetNodeContent();
            }
            else if (child->GetName() == wxT("type"))
            {
                out->m_ctx = wxString2PackageSubstituteInfoContext(child->GetNodeContent());
            }

            // proceed
            child = child->GetNext();
        }

        return true;
    }
};


// ----------------------------------------------------------------------------
// wxPackageHTMLOutputFormat
// ----------------------------------------------------------------------------

bool wxPackageHTMLOutputFormat::Load(const wxString &dirname)
{
    wxString summaryfile = dirname + wxFileName::GetPathSeparator() + wxT("summary.html");
    wxString detailsfile = dirname + wxFileName::GetPathSeparator() + wxT("details.html");
    wxString descfile = dirname + wxFileName::GetPathSeparator() + wxT("info.xml");
    wxFFile f;

    if (!wxFileExists(summaryfile) || !wxFileExists(detailsfile) || !wxFileExists(descfile))
    {
        // the given directory does not contain a valid view format
        wxLogWarning(_("The directory '%s' does not contain a valid view format."),
                     dirname.c_str());
        return false;
    }

    // summary
    if (!f.Open(summaryfile) || !f.ReadAll(&m_strSummary))
    {
        wxLogError(_("Could not load the '%s' file."), summaryfile.c_str());
        return false;
    }
    f.Close();

    // details
    if (!f.Open(detailsfile) || !f.ReadAll(&m_strDetails))
    {
        wxLogError(_("Could not load the '%s' file."), detailsfile.c_str());
        return false;
    }
    f.Close();

    // look at the XML specification file
    wxPackageHTMLOutputFormatXMLDescriptor desc;
    if (!desc.Load(descfile, this))
    {
        wxLogError(_("Could not load the '%s' file."), descfile.c_str());
        return false;
    }

    return true;
}

wxString wxPackageHTMLOutputFormat::GetSummaryFor(const wxPackageInfo &pkg) const
{
    return pkg.SubstituteInfo(m_strSummary, m_ctx);
}

wxString wxPackageHTMLOutputFormat::GetDetailsFor(const wxPackageInfo &pkg) const
{
    return pkg.SubstituteInfo(m_strDetails, m_ctx);
}

