/*
 * Copyright (c) Contributors to the Open 3D Engine Project.
 * For complete copyright and license terms please see the LICENSE at the root of this distribution.
 *
 * SPDX-License-Identifier: Apache-2.0 OR MIT
 *
 */

#include <AtomToolsFramework/Document/AtomToolsDocumentInspector.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Inspector/InspectorPropertyGroupWidget.h>

namespace AtomToolsFramework
{
    AtomToolsDocumentInspector::AtomToolsDocumentInspector(const AZ::Crc32& toolId, QWidget* parent)
        : InspectorWidget(parent)
        , m_toolId(toolId)
    {
        AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
    }

    AtomToolsDocumentInspector::~AtomToolsDocumentInspector()
    {
        AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
    }

    void AtomToolsDocumentInspector::SetDocumentId(const AZ::Uuid& documentId)
    {
        AddGroupsBegin();

        m_documentId = documentId;

        AtomToolsDocumentRequestBus::Event(
            m_documentId,
            [&](AtomToolsDocumentRequests* documentRequests)
            {
                if (documentRequests->IsOpen())
                {
                    // Create a unique settings prefix string per document using a CRC of the document path
                    const AZStd::string groupSettingsPrefix = m_documentSettingsPrefix +
                        AZStd::string::format("/%08x/GroupSettings", aznumeric_cast<AZ::u32>(AZ::Crc32(documentRequests->GetAbsolutePath())));
                    SetGroupSettingsPrefix(groupSettingsPrefix);

                    // This will automatically expose all document contents to an inspector with a collapsible group per object.
                    // In the case of the material editor, this will be one inspector group per property group.
                    for (auto& objectInfo : documentRequests->GetObjectInfo())
                    {
                        // Passing in same main and comparison instance to enable custom value comparison
                        const AZ::Crc32 groupSaveStateKey(
                            AZStd::string::format("%s/%s", groupSettingsPrefix.c_str(), objectInfo.m_name.c_str()));
                        auto propertyGroupWidget = new InspectorPropertyGroupWidget(
                            objectInfo.m_objectPtr, objectInfo.m_objectPtr, objectInfo.m_objectType, this, this, groupSaveStateKey, {},
                            m_nodeIndicatorFunction, 0);

                        AddGroup(objectInfo.m_name, objectInfo.m_displayName, objectInfo.m_description, propertyGroupWidget);
                        SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
                    }
                }

                InspectorRequestBus::Handler::BusConnect(m_documentId);
            });

        AddGroupsEnd();
    }

    void AtomToolsDocumentInspector::SetDocumentSettingsPrefix(const AZStd::string& prefix)
    {
        m_documentSettingsPrefix = prefix;
    }

    void AtomToolsDocumentInspector::SetIndicatorFunction(const NodeIndicatorFunction& indicatorFunction)
    {
        m_nodeIndicatorFunction = indicatorFunction;
    }

    void AtomToolsDocumentInspector::Reset()
    {
        m_documentId = AZ::Uuid::CreateNull();
        m_editInProgress = false;

        InspectorWidget::Reset();
    }

    void AtomToolsDocumentInspector::OnDocumentObjectInfoChanged(
        [[maybe_unused]] const AZ::Uuid& documentId, const DocumentObjectInfo& objectInfo, bool rebuilt)
    {
        if (m_documentId == documentId)
        {
            SetGroupVisible(objectInfo.m_name, objectInfo.m_visible);
            if (rebuilt)
            {
                RebuildGroup(objectInfo.m_name);
            }
            else
            {
                RefreshGroup(objectInfo.m_name);
            }
        }
    }

    void AtomToolsDocumentInspector::BeforePropertyModified([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode)
    {
        if (!m_editInProgress)
        {
            m_editInProgress = true;
            AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsDocumentRequestBus::Events::BeginEdit);
        }
    }

    void AtomToolsDocumentInspector::SetPropertyEditingComplete([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode)
    {
        if (m_editInProgress)
        {
            m_editInProgress = false;
            AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsDocumentRequestBus::Events::EndEdit);
        }
    }
} // namespace AtomToolsFramework

//#include <AtomToolsFramework/Document/moc_AtomToolsDocumentInspector.cpp>
