/*
* Copyright (C) 2004 TES Electronic Solutions GmbH,
* All Rights Reserved.
* This source code and any compilation or derivative thereof is the
* proprietary information of TES Electronic Solutions GmbH
* and is confidential in nature.
* Under no circumstances is this software to be exposed to or placed
* under an Open Source License of any type without the expressed
* written permission of TES Electronic Solutions GmbH
*
*############################################################
*/

#include "StreamRuntimeGUI.h"
#include "StreamRuntimeConfig.h"

#include "GUIProfiler.h"
#include "GUIProperties.h"
#include "GUILocalisationHandler.h"
#include "GUIResourceFileHandler.h"
#include "GUIResourceManager.h"
#include "GUIPropertyResource.h"

#include "GfxWrap.h"
#include "GUIFactoryManager.h"
#include "CustomExtensionFactory.h"
#include "GUITrace.h"

#ifdef GUILIANI_STREAM_GUI
#include "GUIStreamReaderBinary.h"
#include "GUIStreamReaderXML.h"
#endif

#ifdef GUILIANI_WRITE_GUI
#include "GUIStreamWriterXML.h"
#endif

#ifdef GUILIANI_ANIMATION_ACTIVE
#include "GUIAnimationHandler.h"
#endif

#include "CustomExtensionFuncs.h"
#include "CustomStandardFactory.h"

#include "GUIException.h"
#include "GUIDataPool.h"
#include "GUIEvent.h"
#include "GUIFileSysWrap.h"

#include "GUIBitmapWriter.h"

#include "GUIMemLeakDetection.h"
#include "GUIMemLeakWatcher.h"

namespace NStreamRuntime
{
    Configurator* CStreamRuntimeGUI::ms_pkConfigurator = NULL;

    CStreamRuntimeGUI::CStreamRuntimeGUI(
        eC_Value x, eC_Value y,
        eC_Value width, eC_Value height,
        ObjectHandle_t eID) :
        CGUI(x, y, width, height, eID),
        m_bBackgroundEnabled(true),
        m_uiBackgroundColor(0xffffffff)
#ifdef GUILIANI_STREAM_GUI
        ,m_pkStreamReader(NULL, false)
#endif
    {
        Init();
    }

    CStreamRuntimeGUI::~CStreamRuntimeGUI()
    {
#ifdef GUILIANI_STREAM_GUI
        CGUIFactoryManager::DeleteInstance();
#endif
    }

    void CStreamRuntimeGUI::Init()
    {
        if (NULL == ms_pkConfigurator)
            return;

        m_bBackgroundEnabled = ms_pkConfigurator->IsBackgroundEnabled();
        m_uiBackgroundColor = ms_pkConfigurator->GetBackgroundColor();

        // we set ResourcePathPrefix from config file only if it's not empty.
        eC_String kResourcePathPrefix = ms_pkConfigurator->GetResourcePathPrefix();
        if (!kResourcePathPrefix.IsEmpty())
        {
            GETRESHANDLER.SetResourcePathPrefix(kResourcePathPrefix);
        }

        // Dynamically registered resources shall not be automatically unloaded if their request count reaches zero.
        // In a Gui created within GSE basically ALL resources will be dynamic.
        GETRESMANAGER.KeepDynamicImages(true);
        GETRESMANAGER.KeepDynamicFonts(true);
        GETRESMANAGER.KeepDynamicSounds(true);
        GETRESMANAGER.KeepDynamicGeneralResources(true);

        SetFocussable(true);
        GUI_TRY
        {
#ifdef GUILIANI_STREAM_GUI
            GUI_TRY
            {
                CGUIFactoryManager::CreateInstance();

                // Add the factory for Guiliani's standard widgets first
#ifdef STREAMRUNTIME_CUSTOM_STANDARD_FACTORY_EXISTS
                GETFACTORY.AddUserFactory(new CustomStandardFactory());
#else
                GETFACTORY.AddUserFactory(new CGUIStandardFactory());
#endif

                // Add factory for custom extensions
                GETFACTORY.AddUserFactory(GETEXTENSIONSFACTORY, false);
                // Dependant on StreamRuntime configuration the necessary StreamReader is
                // created (XML or binary streaming mode).
                GETFACTORY.SetDefaultStreamingMode(ms_pkConfigurator->GetStreamingMode());

                switch (GETFACTORY.GetDefaultStreamingMode())
                {
                case FILE_TYPE_XML:
                    // XML based dialog files.
                    m_pkStreamReader = new CGUIStreamReaderXML();
                    break;

                case FILE_TYPE_BINARY:
                    // Guiliani binary based dialog files.
                    m_pkStreamReader = new CGUIStreamReaderBinary();
                    break;

                case FILE_TYPE_CUSTOM:
                    GUILOG(GUI_TRACE_ERROR, "unknown file-type.\n");
                    break;
                }
            }
            GUI_CATCH_ALL
            {
                GUILOG_THROW_EXCEPTION(CGUIException(), "Init: CGUIFactoryManager and StreamReaders could not be created.\n");
            }
#endif

            // Now let's start the GUI:
            // let the factory create the objects, getting the arguments for the construction from the streaming file
            StreamGUI();

            // Trigger an initial refresh of the screen
            GETGFX.InvalidateRect(0, 0, eC_FromInt(GETGFX.GetPhysicalScreenWidth()), eC_FromInt(GETGFX.GetPhysicalScreenHeight()));
        }
        GUI_CATCH_ALL
        {
            // As the CGUI destructor functionality is not automatically called when leaving via an exception
            // we clean up here explicitly
            RemoveAllChildren();
            GUI_THROW(0);
        }
    }

    void CStreamRuntimeGUI::StreamGUI()
    {
#ifdef GUILIANI_STREAM_GUI
        if (NULL != ms_pkConfigurator)
        {
            // since version 4 the filenames are not completely stored
            if (ms_pkConfigurator->GetVersion() >= 4)
            {
                GETRESMANAGER.SetPredictResourceFileExtension(true);
                GETRESMANAGER.SetAddResourceFilePrefix(true);
            }

            // Load the initial language
            eC_String kFileName = ms_pkConfigurator->GetLanguageFileName();
            if (!kFileName.IsEmpty())
            {
                GETLOCALEHDL.LoadLocalisationFile(kFileName);
            }

            // Register images, fonts, sounds etc. via resource files (if configured)
            kFileName = ms_pkConfigurator->GetPropertyFileName();
            if (!kFileName.IsEmpty())
            {
                GETPROPHDL.ReadGlobalPropertiesFromFile(kFileName);
            }

            kFileName = ms_pkConfigurator->GetImageFileName();
            if (!kFileName.IsEmpty())
            {
                GETRESMANAGER.RegisterImageResourcesFromFile(kFileName);
            }

            kFileName = ms_pkConfigurator->GetFontFileName();
            if (!kFileName.IsEmpty())
            {
                GETRESMANAGER.RegisterFontResourcesFromFile(kFileName);
            }

            kFileName = ms_pkConfigurator->GetSoundFileName();
            if (!kFileName.IsEmpty())
            {
                GETRESMANAGER.RegisterSoundResourcesFromFile(kFileName);
            }

            kFileName = ms_pkConfigurator->GetGenResFileName();
            if (!kFileName.IsEmpty())
            {
                GETRESMANAGER.RegisterGeneralResourcesFromFile(kFileName);
            }

            // Load the DataPool file
            kFileName = ms_pkConfigurator->GetDataPoolFileName();
            if (!kFileName.IsEmpty())
            {
                CGUIDataPool::ReadDataPoolFromFile(kFileName);
            }

#ifdef GUILIANI_ANIMATION_ACTIVE
            kFileName = ms_pkConfigurator->GetAnimationsFileName();
            if (!kFileName.IsEmpty())
            {
                GETANIMATIONHDL.ReadAnimationsFromFile(kFileName);
            }
#endif

            // Load initial dialog
            kFileName = ms_pkConfigurator->GetDialogFileName();
            if (kFileName.IsEmpty())
            {
                GUILOG(GUI_TRACE_ERROR, "StreamGUI: No dialog name configured.\n");
            }
            else
            {
                RemoveAllChildren();
                AddObject(GETFACTORY.LoadDialogFromFile(kFileName));
            }
        }
#endif
    }

    eC_Bool CStreamRuntimeGUI::DoDraw()
    {
        // If the configuration requests us to fill the background in a given color
        if (m_bBackgroundEnabled)
        {
            GETGFX.SetForegroundColor(m_uiBackgroundColor);
            GETGFX.FilledRect(GetAbsRect());
            return true;
        }
        return false;
    }

#ifdef STREAMRUNTIME_USE_SHORTCUTS
    eC_Bool CStreamRuntimeGUI::DoKeyDown(const GUIKeyIdentifier_t& eKeyID, const eC_UInt& uiModifiers)
    {
        if (eKeyID == GK_F1)
        {
            CGUIBitmapWriter::CreateScreenshot("screenshot");
        }
        else if (eKeyID == GK_F2)
        {
            eC_Bool bActive = GETPROFILER.IsCPUProfilingActive();
            GETPROFILER.SetCPUProfilingActive(!bActive);
            GETPROFILER.SetGraphicsProfilingActive(!bActive);
            GETGUI.InvalidateArea();
        }
        else if (eKeyID == GK_F3)
        {
            eC_Bool bActive = GETPROFILER.IsMemoryProfilingActive();
            GETPROFILER.SetMemoryProfilingActive(!bActive);
            GETPROFILER.SetMemoryUsageBarActive(!bActive);
            GETGUI.InvalidateArea();
        }
        else if (eKeyID == GK_F4)
        {
            GETPROFILER.SetInvalidationActive(!GETPROFILER.IsInvalidationActive());
            GETGUI.InvalidateArea();
        }
#ifdef GUILIANI_WRITE_GUI
        else if (eKeyID == GK_F5)
        {
            CGUIAutoPtr<eC_File> pkOutputFile(GETFILESYS.OpenPlatformFile("export.xml", eC_File::FS_WRITEACCESS), false);
            if (pkOutputFile.get()->IsOpen())
            {
                CGUIStreamWriterXML kWriter;
                kWriter.SetStreamingFile(pkOutputFile.get());
                GETGUI.WriteToStream(true);
            }
        }
#endif
        return false;
    }
#endif

    void CStreamRuntimeGUI::SetConfigurator(Configurator* pkConfigurator)
    {
        ms_pkConfigurator = pkConfigurator;
    }
}
