#include "ReplaceReferenceCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/references.h>

namespace UsdLayerManager {

ReplaceReferenceCommand::ReplaceReferenceCommand(pxr::UsdStageRefPtr      stage,
                                                 const pxr::SdfPath&      primPath,
                                                 const pxr::SdfReference& oldRef,
                                                 const pxr::SdfReference& newRef)
    : m_stage(stage)
    , m_primPath(primPath)
    , m_oldRef(oldRef)
    , m_newRef(newRef)
    , m_description("Replace Reference on " + primPath.GetString())
{
}

void ReplaceReferenceCommand::Execute() { Apply(m_oldRef, m_newRef); }
void ReplaceReferenceCommand::Undo()    { Apply(m_newRef, m_oldRef); }

void ReplaceReferenceCommand::Apply(const pxr::SdfReference& toRemove,
                                    const pxr::SdfReference& toAdd)
{
    if (!m_stage) return;
    pxr::UsdPrim prim = m_stage->GetPrimAtPath(m_primPath);
    if (!prim.IsValid()) {
        LOG_ERROR("ReplaceReferenceCommand::Apply: prim not valid " + m_primPath.GetString());
        return;
    }
    try {
        pxr::UsdReferences refs = prim.GetReferences();
        if (!refs.RemoveReference(toRemove))
            LOG_ERROR("ReplaceReferenceCommand: failed to remove reference");
        if (!refs.AddReference(toAdd))
            LOG_ERROR("ReplaceReferenceCommand: failed to add reference");
    } catch (const std::exception& e) {
        LOG_ERROR(std::string("ReplaceReferenceCommand::Apply error: ") + e.what());
    }
}

} // namespace UsdLayerManager
