//
// Generated by dtk
// Translation Unit: J2DPane.cpp
//

#include "JSystem/J2DGraph/J2DPane.h"
#include "JSystem/J2DGraph/J2DGrafContext.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#include "JSystem/JSupport/JSURandomInputStream.h"
#include "dolphin/gx/GXEnum.h"
#include "dolphin/gx/GX.h"
#include "dolphin/types.h"

/* 802CF8F4-802CF984       .text __ct__7J2DPaneFv */
J2DPane::J2DPane() : mPaneTree(this) {
    mMagic = 'PAN1';
    mVisible = true;
    mTag = 0;

    mBounds.set(0.0f, 0.0f, 0.0f, 0.0f);
    initiate();
}

/* 802CF984-802CFA44       .text __ct__7J2DPaneFP7J2DPanebUlRCQ29JGeometry8TBox2<f> */
J2DPane::J2DPane(J2DPane* pPane, bool visible, u32 tag, const JGeometry::TBox2<f32>& bounds)
    : mPaneTree(this) {
    mMagic = 'PAN1';
    mVisible = visible;
    mTag = tag;
    mBounds.set(bounds);
    if (pPane) {
        pPane->mPaneTree.appendChild(&mPaneTree);
    }
    initiate();
}

/* 802CFA44-802CFAE4       .text __ct__7J2DPaneFUlRCQ29JGeometry8TBox2<f> */
J2DPane::J2DPane(u32 tag, const JGeometry::TBox2<f32>& bounds) : mPaneTree(this) {
    mMagic = 'PAN1';
    mVisible = true;
    mTag = tag;
    mBounds.set(bounds);
    initiate();
}

/* 802CFAE4-802CFB48       .text initiate__7J2DPaneFv */
void J2DPane::initiate() {
    mBasePosition.x = 0.0f;
    mBasePosition.y = 0.0f;
    mRotationAxis = ROTATE_Z;
    mRotation = 0.0f;
    mCullMode = GX_CULL_NONE;
    mAlpha = 0xFF;
    mInheritAlpha = TRUE;
    mDrawAlpha = 0xFF;
    mIsConnectParent = 0;
    calcMtx();
}

/* 802CFB48-802CFC00       .text __ct__7J2DPaneFP7J2DPaneP20JSURandomInputStream */
J2DPane::J2DPane(J2DPane* pParentPane, JSURandomInputStream* pStream) : mPaneTree(this) {
    J2DPaneHeader header;

    int pos = pStream->getPosition();
    pStream->read(&header, sizeof(header));
    mMagic = header.mMagic;
    pos += header.mSize;
    makePaneStream(pParentPane, pStream);
    pStream->seek(pos, JSUStreamSeekFrom_SET);
}

/* 802CFC00-802CFEF8       .text makePaneStream__7J2DPaneFP7J2DPaneP20JSURandomInputStream */
void J2DPane::makePaneStream(J2DPane* pParentPane, JSURandomInputStream* pStream) {
    u8 size;
    pStream->read(&size, 1);
    pStream->read(&mVisible, 1);
    pStream->skip(2);
    mTag = pStream->read32b();

    f32 x0 = pStream->readS16();
    f32 y0 = pStream->readS16();
    f32 x1 = x0 + pStream->readS16();
    f32 y1 = y0 + pStream->readS16();
    mBounds.set(x0, y0, x1, y1);

    size -= 6;
    mRotation = 0;
    if (size != 0) {
        mRotation = pStream->readU16();
        size--;
    }

    if (size != 0) {
        setBasePosition((J2DBasePosition)pStream->readU8());
        size--;
    } else {
        setBasePosition(J2DBasePosition_0);
    }

    mAlpha = 0xFF;

    if (size != 0) {
        mAlpha = pStream->readU8();
        size--;
    }

    mInheritAlpha = TRUE;
    if (size != 0) {
        mInheritAlpha = pStream->readU8() != 0;
        size--;
    }

    pStream->align(4);
    if (pParentPane != NULL) {
        pParentPane->mPaneTree.appendChild(&mPaneTree);
    }

    mCullMode = GX_CULL_NONE;
    mDrawAlpha = 0xFF;
    mIsConnectParent = 0;
    calcMtx();
}

/* 802CFEF8-802CFFD8       .text __dt__7J2DPaneFv */
J2DPane::~J2DPane() {
    JSUTreeIterator<J2DPane> iterator;
    for (iterator = mPaneTree.getFirstChild(); iterator != mPaneTree.getEndChild();) {
        J2DPane* child = (iterator++).getObject();
        delete child;
    }
}

/* 802CFFD8-802D0078       .text insertChild__7J2DPaneFP7J2DPaneP7J2DPane */
bool J2DPane::insertChild(J2DPane* pPrev, J2DPane* pChild) {
    if (pPrev == NULL || pChild == NULL)
        return false;

    bool result =
        mPaneTree.insertChild(pPrev != NULL ? &pPrev->mPaneTree : NULL, &pChild->mPaneTree);

    if (result) {
        pChild->calcMtx();
    }

    return result;
}

/* 802D0078-802D054C       .text draw__7J2DPaneFffPC14J2DGrafContextb */
void J2DPane::draw(f32 x, f32 y, const J2DGrafContext* pCtx, bool clip) {
    J2DGrafContext ctx = *pCtx;

    if (pCtx->getGrafType() != 1)
        clip = false;

    JSUTree<J2DPane> * pParent = mPaneTree.getParent();
    J2DPane * pParentPane = NULL;
    if (pParent != NULL)
        pParentPane = pParent->getObject();

    if (mVisible && mBounds.isValid()) {
        mScreenBounds = mBounds;
        mDrawBounds = mBounds;

        if (pParentPane != NULL) {
            JGeometry::TBox2<f32> screenBounds = pParentPane->mScreenBounds;
            mScreenBounds.addPos(screenBounds.i.x, screenBounds.i.y);
            MTXConcat(pParentPane->mDrawMtx, mMtx, mDrawMtx);

            if (clip) {
                JGeometry::TBox2<f32> screenBounds = pParentPane->mScreenBounds;
                mDrawBounds.addPos(screenBounds.i.x, screenBounds.i.y);
                mDrawBounds.intersect(pParentPane->mDrawBounds);
            }

            mDrawAlpha = mAlpha;
            if (mInheritAlpha)
                mDrawAlpha = (mAlpha * pParentPane->mDrawAlpha) / 0xFF;
        } else {
            mScreenBounds.addPos(x, y);
            makeMatrix(mBounds.i.x + x, mBounds.i.y + y);
            MTXCopy(mMtx, mDrawMtx);
            mDrawBounds.set(mScreenBounds);
            mDrawAlpha = mAlpha;
        }

        JGeometry::TBox2<f32> clipBounds(0.0f, 0.0f, 0.0f, 0.0f);
        if (clip)
            ((J2DOrthoGraph*)pCtx)->scissorBounds(&clipBounds, &mDrawBounds);

        if (mDrawBounds.isValid() || !clip) {
            ctx.place(mScreenBounds);
            if (clip) {
                ctx.scissor(clipBounds);
                ctx.setScissor();
            }
            GXSetCullMode((GXCullMode)mCullMode);
            drawSelf(x, y, &ctx.mPosMtx);

            for (JSUTreeIterator<J2DPane> iter = mPaneTree.getFirstChild(); iter != mPaneTree.getEndChild(); ++iter)
                iter->draw(0.0f, 0.0f, pCtx, clip);
        }
    }
}

/* 802D054C-802D05C8       .text move__7J2DPaneFff */
void J2DPane::move(f32 x, f32 y) {
    JGeometry::TBox2<f32> bounds;
    f32 width = mBounds.getWidth(), height = mBounds.getHeight();
    bounds.set(x, y, x + width, y + height);
    mBounds = bounds;
    calcMtx();
}

/* 802D05C8-802D0604       .text add__7J2DPaneFff */
void J2DPane::add(f32 px, f32 py) {
    move(mBounds.i.x + px, mBounds.i.y + py);
}

/* 802D0604-802D0680       .text clip__7J2DPaneFRCQ29JGeometry8TBox2<f> */
void J2DPane::clip(const JGeometry::TBox2<f32>& bounds) {
    JGeometry::TBox2<f32> boxA(bounds);
    JGeometry::TBox2<f32> boxB(mScreenBounds);
    boxA.addPos(boxB.i);
    mDrawBounds.intersect(boxA);
}

/* 802D0680-802D0714       .text search__7J2DPaneFUl */
J2DPane* J2DPane::search(u32 tag) {
    if (tag == mTag) {
        return this;
    }

    JSUTreeIterator<J2DPane> iter;
    for (iter = mPaneTree.getFirstChild(); iter != mPaneTree.getEndChild(); ++iter) {
        if (J2DPane* result = iter.getObject()->search(tag)) {
            return result;
        }
    }
    return NULL;
}

/* 802D0714-802D0800       .text makeMatrix__7J2DPaneFff */
void J2DPane::makeMatrix(f32 x, f32 y) {
    Mtx stack1, stack2, stack3;
    if (mRotation != 0.0f) {
        MTXTrans(stack1, -mBasePosition.x, -mBasePosition.y, 0.0f);
        f32 rot = mRotationAxis == ROTATE_Z ? -mRotation : mRotation;
        MTXRotRad(stack2, mRotationAxis, rot * 0.017453292f);
        MTXTrans(stack3, mBasePosition.x + x, mBasePosition.y + y, 0.0f);
        MTXConcat(stack2, stack1, mMtx);
        MTXConcat(stack3, mMtx, mMtx);
    } else {
        MTXTrans(mMtx, x, y, 0.0f);
    }
}

/* 802D0800-802D08D8       .text setBasePosition__7J2DPaneF15J2DBasePosition */
void J2DPane::setBasePosition(J2DBasePosition pos) {
    /* Nonmatching */
    m2DBasePosition = pos;

    if (pos % 3 == 0) {
        mBasePosition.x = 0.0f;
    } else if (pos % 3 == 1) {
        mBasePosition.x = mBounds.getWidth() / 2.0f;
    } else {
        mBasePosition.x = mBounds.getWidth();
    }

    if (pos / 3 == 0) {
        mBasePosition.y = 0.0f;
    } else if (pos / 3 == 1) {
        mBasePosition.y = mBounds.getHeight() / 2.0f;
    } else {
        mBasePosition.y = mBounds.getHeight();
    }
    mRotationAxis = ROTATE_Z;
    calcMtx();
}
