/////////////////////////////////////////////////////////////////////////////
// Name:        app.cpp
// Purpose:     wxWidgets Package Manager
// Author:      Julian Smart, Francesco Montorsi
// Modified by:
// Created:     2004-11-08
// RCS-ID:      $Id: app.cpp,v 1.6 2007/01/23 18:26:21 frm Exp $
// Copyright:   (c) Julian Smart
// Licence:     wxWidgets license
/////////////////////////////////////////////////////////////////////////////


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

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#include <wx/artprov.h>
#include <wx/cmdline.h>
#include <wx/tokenzr.h>
#include <wx/sysopt.h>
#include <wx/help.h>
#include <wx/cshelp.h>
#include <wx/image.h>
#include <wx/config.h>
#include <wx/stdpaths.h>
#include <wx/msgdlg.h>

#include <wx/fs_mem.h>
#include <wx/fs_arc.h>
#include <wx/fs_filter.h>

#include "wxp/wxp.h"
#include "wxp/fs_wxz.h"

#include "guipm/smartmsgdlg.h"
#include "wx/cachedfs_inet.h"

// wxPM own headers
#include "symbols.h"
#include "mainfrm.h"
#include "app.h"



// ----------------------------------------------------------------------------
// wxPackageManager constants
// ----------------------------------------------------------------------------

#define wxPMAPP_HELP_SWITCH                     wxT("h")
#define wxPMAPP_VERSION_SWITCH                  wxT("v")
#define wxPMAPP_PREFIX_OPTION                   wxT("p")

static const wxCmdLineEntryDesc g_cmdLineDesc[] =
{
    { wxCMD_LINE_SWITCH, wxPMAPP_HELP_SWITCH, wxT("help"), wxT("displays help on the command line parameters") },
    { wxCMD_LINE_SWITCH, wxPMAPP_VERSION_SWITCH, wxT("version"), wxT("print version") },

#ifdef __UNIX__
    { wxCMD_LINE_OPTION, wxPMAPP_PREFIX_OPTION, wxT("prefix"), wxT("set program prefix") },
#endif

    { wxCMD_LINE_PARAM, wxT(""), wxT(""), wxT("WXZ file to load"), wxCMD_LINE_VAL_STRING,
      wxCMD_LINE_PARAM_OPTIONAL },

    { wxCMD_LINE_NONE }
};



// ----------------------------------------------------------------------------
// wxPackageManagerApp
// ----------------------------------------------------------------------------

IMPLEMENT_APP(wxPackageManagerApp)

wxPackageManagerApp::wxPackageManagerApp()
{
    // this is not our real name; see cmnsymbols.h for more info
    SetAppName(APPNAME);
}

wxPackageManagerApp::~wxPackageManagerApp()
{
}

bool wxPackageManagerApp::OnInit()
{
    wxLog::SetTimestamp(NULL);

    // VERY IMPORTANT: do not change our working directory otherwise
    //                 we won't be able to load packages with relative paths
    //                 given to arguments of this program
    // wxSetWorkingDirectory(wxStandardPaths::Get().GetDataDir());

    // Parse command line
    wxString cmdFilename;
    wxCmdLineParser cmdParser(g_cmdLineDesc, argc, argv);
    if (cmdParser.Parse() != 0)
        return false;

    if (cmdParser.Found(wxPMAPP_HELP_SWITCH))
    {
        cmdParser.Usage();
        return false;
    }

    if (cmdParser.Found(wxPMAPP_VERSION_SWITCH))
    {
#ifndef __WXMSW__
        wxLog::SetActiveTarget(new wxLogStderr);
#endif
        wxString msg;
        wxString date(wxString::FromAscii(__DATE__));
        msg.Printf(wxT("wxWidgets Package Manager, (c) Julian Smart, Francesco Montorsi 2006 Version %.1f, %s"),
                   VERSION_NUMBER, (const wxChar*) date);
        wxLogMessage(msg);
        return FALSE;
    }

#ifdef __UNIX__
    wxString str;
    if (cmdParser.Found(wxPMAPP_PREFIX_OPTION, &str))
    {
        // do not autodetect the prefix
        ((wxStandardPaths&)wxStandardPaths::Get()).SetInstallPrefix(str);
    }
#endif

    wxString basepath = wxStandardPaths::Get().GetDataDir() +
                        wxFileName::GetPathSeparator();

    if (cmdParser.GetParamCount() > 0)
    {
        cmdFilename = cmdParser.GetParam(0);
#ifdef __WXMSW__
        // Under Windows when invoking via a data file
        // in Explorer, we are passed the short form, for some reason.
        // So normalize and make the long form.
        wxFileName fName(cmdFilename);
        fName.Normalize(wxPATH_NORM_LONG);
        cmdFilename = fName.GetFullPath();
#endif
        //wxMessageBox(cmdFilename);
    }

    // init config object
    SetGlobalConfig();
    wxSmartMessageDialog::SetConfig(wxConfig::Get(), wxT("/Questions"));

    // init most widely used image format handlers
    wxImage::AddHandler( new wxPNGHandler );
    wxImage::AddHandler( new wxJPEGHandler );
    wxImage::AddHandler( new wxGIFHandler );
    wxImage::AddHandler( new wxXPMHandler );

    // wxCachedInternetFSHandler is automatically added
    // by a wxModule which it implements
    // not needed: wxFileSystem::AddHandler(new wxCachedInternetFSHandler);
    wxFileSystem::AddHandler(new wxCachedInternetFSHandler);
    wxFileSystem::AddHandler(new wxMemoryFSHandler);

    // the following are required for correct handling of 
    // packages compressed both as .tar.gz and as .zip:
    wxFileSystem::AddHandler(new wxFilterFSHandler);
    wxFileSystem::AddHandler(new wxArchiveFSHandler);
    wxFileSystem::AddHandler(new wxWxzFSHandler);

#define ICONSZ      wxSize(10, 10)

    // init memory FS
    wxString imgpath = basepath + wxT("images") + wxFileName::GetPathSeparator() + wxT("wxlogo.png");
    wxImage logo;
    if (!logo.LoadFile(imgpath))
    {
        wxLogError(_("Could not load the image '%s'."), imgpath.c_str());
        wxLogError(_("Cannot proceed without a data file. Aborting."));
        return false;
    }

    wxMemoryFSHandler::AddFile(wxT("wxlogo.png"), logo, wxBITMAP_TYPE_JPEG);
    wxMemoryFSHandler::AddFile(
                   wxT("tickmark"),
                   wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, ICONSZ),
                   wxBITMAP_TYPE_XPM );
    wxMemoryFSHandler::AddFile(
                   wxT("crossmark"),
                   wxArtProvider::GetBitmap(wxART_CROSS_MARK, wxART_OTHER, ICONSZ),
                   wxBITMAP_TYPE_XPM );

    // init sockets
    wxSocketBase::Initialize();

    // init help
    wxHelpProvider::Set(new wxSimpleHelpProvider);

    // load presets
    if (!wxPresetXMLDescriptor::Load(GetPresetFile()))
    {
        wxLogError(_("Could not load the presets file '%s'; it's not a valid preset file."),
                   GetPresetFile().c_str());

        // do not proceed as without presets the wxPM is quite useless
        wxLogError(_("Cannot proceed without presets. Aborting."));
        return false;
    }

    // load view formats
    wxString viewfmtbasepath = wxStandardPaths::Get().GetDataDir() +
                               wxFileName::GetPathSeparator() +
                               wxT("viewformats");
    if (!wxPackageInfo::LoadStandardOutputFormats(viewfmtbasepath))
    {
        wxLogError(_("Could not load the view format modes from directory '%s'."),
                   viewfmtbasepath.c_str());

        // do not proceed as without presets the wxPM is quite useless
        wxLogError(_("Cannot proceed without view formats. Aborting."));
        return false;
    }

    // after loading preset we must load all static settings of wxPackage API:
    // the compiler settings, known wxbuilds, local repo paths
    if (!wxCompilerSettings::LoadGlobals(wxConfigBase::Get(), wxEmptyString))
    {
    }

    if (!wxWidgetsBuildArray::LoadGlobals(wxConfigBase::Get(), wxEmptyString))
    {
        // show add wx build dialog / initial settings wizard
        // TODO
    }

    if (!wxPackage::LoadGlobals(wxConfigBase::Get(), wxEmptyString))
    {
        // add some default local repos
#ifdef __WXMSW__
        // under Unix the data dir folder is typically read-only (/usr/local/share/...)
        wxPackage::s_arrLocalRepo.Add(wxStandardPaths::Get().GetDataDir() +
                                      wxFileName::GetPathSeparator() + wxT("samples"));
#endif
        // this folder is used by wxPackageBrowserPanel as default path for
        // download/decompressing packages
        wxPackage::s_arrLocalRepo.Add(wxStandardPaths::Get().GetUserDataDir());
    }

    // create the frame
    wxPackageManagerFrame *fr = new wxPackageManagerFrame();
    if (!fr->Create() || !fr->IsOk())
    {
        wxLogError(_("Cannot initialize the package manager frame. Aborting."));
        return false;
    }

    SetTopWindow(fr);

    // load the WXZ given at command-line, if any
    if (cmdParser.GetParamCount() > 0)
        GetMainFrame()->Open(cmdParser.GetParam(0));

    GetTopWindow()->Show(true);
    return true;
}

int wxPackageManagerApp::OnExit(void)
{
    // save compiler-specific settings & known wxbuilds
    wxCompilerSettings::SaveGlobals(wxConfigBase::Get(), wxEmptyString);
    wxWidgetsBuildArray::SaveGlobals(wxConfigBase::Get(), wxEmptyString);
    wxPackage::SaveGlobals(wxConfigBase::Get(), wxEmptyString);

    // save any eventual change to presets
    if (!wxPresetXMLDescriptor::SavePresets(GetPresetFile()))
        wxLogError(_("Could not save the presets file '%s'. All changes to the presets will be lost!"),
                   GetPresetFile().c_str());

    delete wxConfigBase::Set(NULL);
    return 0;
}

wxPackageManagerFrame* wxPackageManagerApp::GetMainFrame()
{
    return wxDynamicCast(GetTopWindow(), wxPackageManagerFrame);
}

wxString wxPackageManagerApp::GetPresetFile() const
{
    return  wxStandardPaths::Get().GetDataDir() +
            wxFileName::GetPathSeparator() +
            wxT("xml") +
            wxFileName::GetPathSeparator() +
            DEFAULT_PRESETS;
}

