/*--------------------------------------------------------------------------
  Project:  Manual 2D Library - m2d
  File:     m2d_pane.cpp

  Copyright (C)2007-2009 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Revision: 1.55 $
 *-------------------------------------------------------------------------*/

#include <nitro.h>
#include <nnsys/misc.h>
#include <ntmv/m2d/debug.h>
#include <ntmv/m2d/common.h>
#include <ntmv/m2d/objectConstructor.h>
#include <ntmv/m2d/pane.h>
#include <ntmv/m2d/drawInfo.h>
#include <ntmv/m2d/page.h>
#include <ntmv/m2d/picture.h>
#include <ntmv/m2d/Rect.h>
#include <cstring>

namespace ntmv
{
namespace m2d
{

NTMV_RNT_RUNTIME_TYPEINFO_ROOT_DEFINITION(Pane);     // Defines an instance of runtime type information

/*---------------------------------------------------------------------------*
  Name:         Pane::Pane

  Description:  Constructor

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
Pane::Pane(
    const res::Pane*    pBlock,
    const ResBlockSet&  resBlockSet
)
{
    Init();

    #if defined(NTMV_M2D_NAMEEMBEDDED)
        mName = detail::GetNamePoolStr(resBlockSet.pNameBlock->offsets, pBlock->nameStrIdx);
        mFlag = pBlock->flag;
    #else
        (void)resBlockSet.pNameBlock->offsets;
    #endif

    mLocalPosition = pBlock->translate;
    mSize = pBlock->size;
}

void
Pane::Init()
{
    mFlag = 0;
    mpParent = 0;
    mChildAry = 0;
    mChildNum = 0;
    mChildMax = 0;
}

/*---------------------------------------------------------------------------*
  Name:         Pane::Finalize

  Description:  Performs shutdown.

  Arguments:    objectConstructor: A reference to an ObjectConstructor object.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
Pane::Finalize(const ObjectConstructor& objectConstructor)
{
    #if defined(NTMV_M2D_NAMEEMBEDDED)
        NTMV_LOG("Pane::Finalize() - [%s]\n", mName);
    #endif

    // Child pane post-processing
    for (int i = 0; i < mChildNum; ++i)
    {
        objectConstructor.DeleteObj(mChildAry[i]);
    }

    objectConstructor.DeletePrimArray(mChildAry);
}

/*---------------------------------------------------------------------------*
  Name:         Pane::AllocChild

  Description:  Allocates memory for child panes.

  Arguments:    objectConstructor: A reference to an ObjectConstructor object.
                paneNum: The number of child panes to allocate.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
Pane::AllocChild(
    const ObjectConstructor&    objectConstructor,
    u16                         paneNum
)
{
    NNS_ASSERT(mChildMax == 0);

    mChildAry = objectConstructor.NewArray<Pane*>(paneNum);
    NNS_NULL_ASSERT(mChildAry);

    mChildMax = paneNum;
}

/*---------------------------------------------------------------------------*
  Name:         Pane::AppendChild

  Description:  Appends a pane to the end of the child pane list.

  Arguments:    pChild: The pane being added

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
Pane::AppendChild(Pane* pChild)
{
    NNS_ASSERT(mChildNum < mChildMax);

    mChildAry[mChildNum++] = pChild;
    pChild->mpParent = this;
}

/*
    Return pane Rect
*/
const Rect
Pane::GetPaneRect() const
{
    Rect ret;

    ret.left   = mPosition.x;
    ret.top    = mPosition.y;
    ret.right  = static_cast<s16>(mPosition.x + mSize.width);
    ret.bottom = static_cast<s16>(mPosition.y + mSize.height);

    return ret;
}

#if defined(NTMV_M2D_NAMEEMBEDDED)
Pane*
Pane::FindPaneByName(
    const char* findName,
    bool        bRecursive
)
{
    if (0 == std::strcmp(mName, findName))
    {
        return this;
    }

    if (bRecursive)
    {
        // Search whether there are matches among the children
        for (int i = 0; i < mChildNum; ++i)
        {
            if (Pane* pPane = mChildAry[i]->FindPaneByName(findName, bRecursive))
            {
                return pPane;
            }
        }
    }

    return 0;
}
#endif

void
Pane::Calc(
    const DrawInfo& drawInfo,
    Point           parentPosition
)
{
    CalcSelf(drawInfo, parentPosition);

    // Child rendering
    for (int i = 0; i < mChildNum; ++i)
    {
        mChildAry[i]->Calc(drawInfo, mPosition);
    }
}

void
Pane::CalcSelf(
    const DrawInfo& /* drawInfo */,
    Point           parentPosition
)
{
    mPosition = mLocalPosition;
    mPosition.Move(parentPosition);
}

void
Pane::Draw(const DrawInfo& drawInfo)
{
    DrawSelf(drawInfo);

    // Child rendering
    for (int i = 0; i < mChildNum; ++i)
    {
        mChildAry[i]->Draw(drawInfo);
    }
}

void
Pane::DrawSelf(const DrawInfo& drawInfo)
{
    #if defined(NNS_DEBUG)

      #if LYT_IMPORT_CODE
        if (mpParent && drawInfo.IsDebugDrawMode())     // Draw frame
        {
            // Matrix
            LoadMtx(drawInfo);

            detail::DrawLine(GetVtxPos(), mSize, ut::Color::GREEN);
        }
      #else
        (void)drawInfo;
      #endif // #if LYT_IMPORT_CODE

    #else   // #if defined(NNS_DEBUG)

        (void)drawInfo;

    #endif  // #if defined(NNS_DEBUG)
}

}   // namespace m2d
}   // namespace ntmv
