#include "BaseNode.h"
#include "EngineCore/Game.h"
BaseNode::BaseNode()
{
    Game::GetInstance().m_nodeCount++;
}

BaseNode::~BaseNode()
{
    Game::GetInstance().m_nodeCount--;
}

void BaseNode::Init()
{
}
void BaseNode::HandleEvents(SDL_Event *e)
{
    // 如果有子节点并含有事件标签，则处理事件
    RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
    while (child)
    {
        if (child->hasTag(Tag::ACTOR) || child->hasTag(Tag::HANDEL_EVENT))
            child->HandleEvents(e);
        child = child->GetNext();
    }
}

void BaseNode::Update(float deltaTime)
{
    // 如果有回调函数，则调用回调函数
    if (cb_update_)
    {
        cb_update_(deltaTime);
    }
    // 如果有子节点并含有刷新标签，则更新子节点
    RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
    while (child)
    {
        if (child->hasTag(Tag::UPDATE))
            child->Update(deltaTime);
        child = child->GetNext();
    }
}

void BaseNode::PreRender()
{
    // 如果有子节点并含有渲染标签，则渲染子节点
    RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
    while (child)
    {
        if (child->hasTag(Tag::RENDER))
            child->PreRender();
        child = child->GetNext();
    }
}

void BaseNode::Render()
{
    // 如果有子节点并含有渲染标签，则渲染子节点
    RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
    while (child)
    {
        if (child->hasTag(Tag::RENDER))
            child->Render();
        child = child->GetNext();
    }
}

void BaseNode::Clear()
{
}

void BaseNode::SetCallbackOnUpdate(const UpdateCallback &cb)
{
    cb_update_ = cb;
}

void BaseNode::SetChildIterationTransform()
{
    Transform n_transform;
    n_transform.position = transform.position + transformIter.position;
    n_transform.scale = transform.scale * transformIter.scale;
    n_transform.rotation = transform.rotation + transformIter.rotation;

    // 如果有子节点并含有transform标签，则设置其位置
    RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
    while (child)
    {
        if (child->hasTag(Tag::TRANSFORM))
            child->SetIterationTransform(n_transform);
        child = child->GetNext();
    }
}

void BaseNode::CalcRenderInfo()
{
}

void BaseNode::SetName(std::string name)
{
    m_Name = name;
}

std::string BaseNode::GetName()
{
    return m_Name;
}

int BaseNode::GetRenderZOrder()
{
    return m_RenderZOrder;
}

void BaseNode::SetRenderZOrder(int zOrder)
{
    m_RenderZOrder = zOrder;
    Reorder();
}

void BaseNode::Reorder()
{
    if (m_Parent)
    {
        RefPtr<BaseNode> me = this;
        m_Parent->m_BaseNodes.Remove(me);
        RefPtr<BaseNode> sibling = m_Parent->m_BaseNodes.GetLast();
        if (sibling && sibling->GetRenderZOrder() > m_RenderZOrder)
        {
            sibling = sibling->GetPrev();
            while (sibling)
            {
                if (sibling->GetRenderZOrder() <= m_RenderZOrder)
                    break;
                sibling = sibling->GetPrev();
            }
        }
        if (sibling)
        {
            m_Parent->m_BaseNodes.InsertAfter(me, sibling);
        }
        else
        {
            m_Parent->m_BaseNodes.PushFront(me);
        }
    }
}

void BaseNode::AddChild(RefPtr<BaseNode> child)
{
    m_BaseNodes.PushBack(child);
    child->OnAdded(this);
    // 如果是需要渲染的子对象
    if (child->hasTag(Tag::RENDER))
    {
        // 重新排序
        child->Reorder();
        // 如果组件有transform标签，则设置其位置
        if (child->hasTag(Tag::TRANSFORM))
        {
            Transform n_transform;
            n_transform.position = transform.position + transformIter.position;
            n_transform.scale = transform.scale * transformIter.scale;
            n_transform.rotation = transform.rotation + transformIter.rotation;
            child->SetIterationTransform(n_transform);
        }
    }
}

void BaseNode::RemoveChild(RefPtr<BaseNode> child)
{
    child->m_Parent = nullptr;
    m_BaseNodes.Remove(child);
}

void BaseNode::RemoveAllChild()
{
    m_BaseNodes.Clear();
}

void BaseNode::OnAdded(BaseNode *node)
{
    m_Parent = node;
}

void BaseNode::SetIterationTransform(Transform n_transform)
{
    if (n_transform == transformIter)
        return;
    transformIter = n_transform;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Transform BaseNode::GetIterationTransform()
{
    return transformIter;
}

void BaseNode::SetTransform(Transform n_transform)
{
    if (n_transform == transform)
        return;
    transform = n_transform;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Transform BaseNode::GetTransform()
{
    return transform;
}

void BaseNode::SetPos(Vec2 pos)
{
    if (pos == this->transform.position)
        return;
    this->transform.position = pos;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Vec2 BaseNode::GetPos()
{
    return this->transform.position;
}

Vec2 BaseNode::GetWorldPos()
{
    return this->transform.position + this->transformIter.position;
}

void BaseNode::SetScale(Vec2 scale)
{
    if (scale == this->transform.scale)
        return;
    this->transform.scale = scale;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Vec2 BaseNode::GetScale()
{
    return this->transform.scale;
}

void BaseNode::SetRotation(float angle)
{
    if (angle == this->transform.rotation)
        return;
    this->transform.rotation = angle;
    CalcRenderInfo();
    SetChildIterationTransform();
}

float BaseNode::GetRotation()
{
    return this->transform.rotation;
}

void BaseNode::SetAnchor(Vec2 anchor)
{
    if (anchor == this->Anchor)
        return;
    Anchor.x = anchor.x;
    Anchor.y = anchor.y;
}

Vec2 BaseNode::GetAnchor()
{
    Vec2 P;
    P.x = Anchor.x;
    P.y = Anchor.y;
    return P;
}

void BaseNode::SetSize(VecSize size)
{
    this->Size = size;
}

VecSize BaseNode::GetSize()
{
    return this->Size;
}

void BaseNode::SetVisible(bool visible)
{
    this->Visible = visible;
}

bool BaseNode::GetVisible()
{
    return this->Visible;
}

void BaseNode::SetAlpha(float alpha)
{
    this->Alpha = alpha;
}

BaseNode *BaseNode::GetParent()
{
    return this->m_Parent;
}

float BaseNode::GetAlpha()
{
    return this->Alpha;
}

void BaseNode::SetIterationPos(Vec2 pos)
{
    if (pos == this->transformIter.position)
        return;
    this->transformIter.position = pos;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Vec2 BaseNode::GetIterationPos()
{
    return this->transformIter.position;
}

void BaseNode::SetIterationScale(Vec2 scale)
{
    if (scale == this->transformIter.scale)
        return;
    this->transformIter.scale = scale;
    CalcRenderInfo();
    SetChildIterationTransform();
}

Vec2 BaseNode::GetIterationScale()
{
    return this->transformIter.scale;
}

void BaseNode::SetIterationRotation(float angle)
{
    if (angle == this->transformIter.rotation)
        return;
    this->transformIter.rotation = angle;
    CalcRenderInfo();
    SetChildIterationTransform();
}

float BaseNode::GetIterationRotation()
{
    return this->transformIter.rotation;
}

void BaseNode::SetBlendMode(LE_BlEND_MODE mode)
{
    this->_BlendMode = mode;
}

LE_BlEND_MODE BaseNode::GetBlendMode()
{
    return this->_BlendMode;
}
