#include "DeerStudio/EditorEngine/DockPanel/DockPanelContext.h"
#include "DeerStudio/EditorEngine.h"
#include "Deer/Log.h"

#include "angelscript.h"
#include <stdint.h>

namespace Deer {
    namespace EditorEngine {
        DockPanelContext::DockPanelContext(asIScriptModule* _module, DockPanelInfo* _info) 
            : module(_module), info(_info) {
                
            size_t nScripts = module->GetObjectTypeCount();
            asITypeInfo* dockPanelType = scriptEngine->GetTypeInfoByName("DockPanel");
            
            if (!dockPanelType) {
                DEER_EDITOR_ENGINE_ERROR("Could not load DockPanel interface type");
                return;
            }

            context = scriptEngine->CreateContext();
            context->AddRef();
            for (size_t i = 0; i < nScripts; i++) {
                asITypeInfo* info = module->GetObjectTypeByIndex(i);

                // If it does not implement dock panel we are not interested int it
                if (!info->Implements(dockPanelType))
                    continue;

                dockPanels.push_back({info, context});
            }

        }

        DockPanelContext::DockPanelContext(DockPanelContext&& dp)
            : dockPanels(std::move(dp.dockPanels)) {
            module = dp.module;
            context = dp.context;
            info = dp.info;

            dp.context = nullptr;
            dp.module = nullptr;
            dp.info = nullptr;
        }

        DockPanelContext& DockPanelContext::operator=(DockPanelContext&& dp) {
            if (&dp != this) {
                dockPanels = std::move(dp.dockPanels);
                module = dp.module;
                context = dp.context;
                info = dp.info;

                dp.context = nullptr;
                dp.module = nullptr;
                dp.info = nullptr;
            }
            return *this;
        }

        void DockPanelContext::init() {
            for (DockPanelObject& panel : dockPanels) {
                currentDockPanelExecution = &panel;
                panel.init();
            }
            
            currentDockPanelExecution = nullptr;
        }

        void DockPanelContext::render() {
            for (DockPanelObject& panel : dockPanels) {
                currentDockPanelExecution = &panel;
                panel.render();
            }

            currentDockPanelExecution = nullptr;
        }

        DockPanelContext::~DockPanelContext() {
            dockPanels.clear();

            if (context)
                context->Release();

            delete info;
        }
    }
}