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

#include "JSystem/J2DGraph/J2DWindow.h"
#include "JSystem/JSupport/JSURandomInputStream.h"
#include "JSystem/JUtility/TColor.h"
#include "JSystem/JUtility/JUTPalette.h"
#include "JSystem/JUtility/JUTResource.h"
#include "JSystem/JUtility/JUTTexture.h"
#include "dolphin/gx/GX.h"

/* 802D12E0-802D1820       .text __ct__9J2DWindowFP7J2DPaneP20JSURandomInputStream */
J2DWindow::J2DWindow(J2DPane* param_0, JSURandomInputStream* param_1) : mpFrameTexture1(NULL), mpFrameTexture2(NULL), mpFrameTexture3(NULL), mpFrameTexture4(NULL), mpContentsTexture(NULL), mpPalette(NULL) {
    /* Nonmatching */
    s32 local_188 = param_1->getPosition();
    u32 header[2];
    param_1->read(header, 8);
    mMagic = header[0];
    s32 end = local_188 + header[1];
    makePaneStream(param_0, param_1);
    JUTResReference stack_178;
    u8 r27 = param_1->readU8();
    f32 f31 = param_1->read16b();
    f32 f30 = param_1->read16b();
    f32 f29 = f31 + param_1->read16b();
    f32 f28 = f30 + param_1->read16b();
    mWindowBox.set(f31, f30, f29, f28);
    ResTIMG* timg = (ResTIMG*)stack_178.getResource(param_1, 'TIMG', NULL);
    if (timg) {
        mpFrameTexture1 = new JUTTexture(timg, 0);
    }
    timg = (ResTIMG*)stack_178.getResource(param_1, 'TIMG', NULL);
    if (timg) {
        mpFrameTexture2 = new JUTTexture(timg, 0);
    }
    timg = (ResTIMG*)stack_178.getResource(param_1, 'TIMG', NULL);
    if (timg) {
        mpFrameTexture3 = new JUTTexture(timg, 0);
    }
    timg = (ResTIMG*)stack_178.getResource(param_1, 'TIMG', NULL);
    if (timg) {
        mpFrameTexture4 = new JUTTexture(timg, 0);
    }
    ResTLUT* tlut = (ResTLUT*)stack_178.getResource(param_1, 'TLUT', NULL);
    if (tlut) {
        mpPalette = new JUTPalette(GX_TLUT0, tlut);
    }
    field_0x110 = param_1->read8b();
    mColorTL.set(param_1->read32b());
    mColorTR.set(param_1->read32b());
    mColorBL.set(param_1->read32b());
    mColorBR.set(param_1->read32b());
    r27 -= 14;
    mpContentsTexture = NULL;
    if (r27) {
        timg = (ResTIMG*)stack_178.getResource(param_1, 'TIMG', NULL);
        if (timg) {
            mpContentsTexture = new JUTTexture(timg, 0);
        }
        r27--;
    }
    mBlack = JUtility::TColor(0);
    mWhite = JUtility::TColor(0xffffffff);
    if (r27) {
        mBlack = JUtility::TColor(param_1->readU32());
        r27--;
    }
    if (r27) {
        mWhite = JUtility::TColor(param_1->readU32());
    }
    param_1->seek(end, JSUStreamSeekFrom_SET);
    initinfo2();
}

/* 802D1820-802D1A9C       .text initinfo2__9J2DWindowFv */
void J2DWindow::initinfo2() {
    if (mpFrameTexture1 && mpFrameTexture2 && mpFrameTexture3 && mpFrameTexture4) {
        mTextureWidth = mpFrameTexture1->getWidth() + mpFrameTexture2->getWidth();
        mTextureHeight = mpFrameTexture1->getHeight() + mpFrameTexture3->getHeight();
    } else {
        mTextureWidth = 1;
        mTextureHeight = 1;
        return;
    }

    field_0x111 = 0;
    JUTTexture* r30 = mpFrameTexture1;
    if (*mpFrameTexture2 != *r30) {
        field_0x111 |= 1;
        r30 = mpFrameTexture2;
    }
    if (*mpFrameTexture4 != *r30) {
        field_0x111 |= 2;
        r30 = mpFrameTexture4;
    }
    if (*mpFrameTexture3 != *r30) {
        field_0x111 |= 4;
    }
}

/* 802D1A9C-802D1B44       .text __dt__9J2DWindowFv */
J2DWindow::~J2DWindow() {
    delete mpFrameTexture1;
    delete mpFrameTexture2;
    delete mpFrameTexture3;
    delete mpFrameTexture4;
    delete mpPalette;
    delete mpContentsTexture;
}

/* 802D1B44-802D1F5C       .text draw_private__9J2DWindowFRCQ29JGeometry8TBox2<f>RCQ29JGeometry8TBox2<f> */
void J2DWindow::draw_private(const JGeometry::TBox2<f32>& frameBox, const JGeometry::TBox2<f32>& contentsBox) {
    /* Nonmatching - not finished yet */
    drawContents(contentsBox);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
    GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXSetNumTexGens(1);

    if (mpFrameTexture1 != NULL && mpFrameTexture2 != NULL && mpFrameTexture3 != NULL && mpFrameTexture4 != NULL) {
        f32 right = frameBox.getWidth() - mpFrameTexture4->getWidth();
        f32 top = frameBox.getHeight() - mpFrameTexture4->getHeight();
        f32 left = frameBox.i.x + mpFrameTexture1->getWidth();
        f32 bottom = frameBox.i.y + mpFrameTexture1->getHeight();

        drawFrameTexture(mpFrameTexture1, 0.0f, 0.0f,
            ((field_0x110 >> 7) & 1),
            ((field_0x110 >> 6) & 1), true);
        drawFrameTexture(mpFrameTexture2, right, 0.0f,
            ((field_0x110 >> 5) & 1),
            ((field_0x110 >> 4) & 1), (field_0x111 & 1));

        u16 local_a6 = ((field_0x110 >> 5) & 1) ? (u16)0x8000 : (u16)0;
        u16 local_a8 = ((field_0x110 >> 4) & 1) ? (u16)0x8000 : (u16)0;
        u16 local_a82 = local_a8 ^ 0x8000;
        drawFrameTexture(mpFrameTexture2, left, 0.0f, right - left, (f32)mpFrameTexture2->getHeight(),
            local_a6, local_a8, local_a6, local_a82, false);

        drawFrameTexture(mpFrameTexture4, right, top,
            ((field_0x110 >> 1) & 1),
            ((field_0x110 >> 0) & 1), (field_0x111 & 1));

        u16 local_aa = ((field_0x110 >> 1) & 1) ? (u16)0x8000 : (u16)0;
        u16 local_ac = ((field_0x110 >> 0) & 1) ? (u16)0 : (u16)0x8000;
        u16 local_ac2 = local_ac ^ 0x8000;
        drawFrameTexture(mpFrameTexture4, left, top, right - left, (f32)mpFrameTexture4->getHeight(),
            local_aa, local_ac, local_aa, local_ac2, false);

        u16 local_ae = ((field_0x110 >> 1) & 1) ? (u16)0 : (u16)0x8000;
        u16 local_ae2 = local_ae ^ 0x8000;
        u16 local_b0 = ((field_0x110 >> 0) & 1) ? (u16)0x8000 : (u16)0;
        drawFrameTexture(mpFrameTexture4, right, bottom, (f32)mpFrameTexture4->getWidth(), top - bottom,
            local_ae, local_b0, local_ae2, local_b0, false);

        drawFrameTexture(mpFrameTexture3, 0.0f, top,
            ((field_0x110 >> 3) & 1),
            ((field_0x110 >> 2) & 1), (field_0x111 & 1));

        u16 local_b2 = ((field_0x110 >> 3) & 1) ? (u16)0 : (u16)0x8000;
        u16 local_b22 = local_b2 ^ 0x8000;
        u16 local_b4 = ((field_0x110 >> 2) & 1) ? (u16)0x8000 : (u16)0;
        drawFrameTexture(mpFrameTexture3, 0.0f, bottom, (f32)mpFrameTexture3->getWidth(), top - bottom,
            local_b2, local_b4, local_b22, local_b4, false);
    }

    GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
    GXSetNumTexGens(0);
    GXSetVtxDesc(GX_VA_TEX0, GX_NONE);
}

/* 802D1F5C-802D207C       .text resize__9J2DWindowFff */
void J2DWindow::resize(f32 w, f32 h) {
    /* Nonmatching - regalloc */
    f32 oldW = getWidth();
    f32 oldH = getHeight();
    J2DPane::resize(w, h);
    mWindowBox.f.x += w - oldW;
    mWindowBox.f.y += h - oldH;
    for (JSUTreeIterator<J2DPane> iter = mPaneTree.getFirstChild(); iter != mPaneTree.getEndChild(); ++iter) {
        if (iter->getTypeID() == 0x13 && iter->isConnectParent()) {
            f32 childW = w - oldW + iter->getWidth();
            f32 childH = h - oldH + iter->getHeight();
            iter->J2DPane::resize(childW, childH);
        }
    }
}

/* 802D207C-802D2128       .text setContentsColor__9J2DWindowFQ28JUtility6TColorQ28JUtility6TColorQ28JUtility6TColorQ28JUtility6TColor */
void J2DWindow::setContentsColor(JUtility::TColor c0, JUtility::TColor c1, JUtility::TColor c2, JUtility::TColor c3) {
    mColorTL.set(c0);
    mColorTR.set(c1);
    mColorBL.set(c2);
    mColorBR.set(c3);
}

/* 802D2128-802D2190       .text drawSelf__9J2DWindowFff */
void J2DWindow::drawSelf(f32 x, f32 y) {
    Mtx m;
    MTXIdentity(m);
    drawSelf(x, y, &m);
}

/* 802D2190-802D2288       .text drawSelf__9J2DWindowFffPA3_A4_f */
void J2DWindow::drawSelf(f32 x, f32 y, Mtx *pMtx) {
    JGeometry::TBox2<f32> screenBounds = mScreenBounds;
    screenBounds.addPos(JGeometry::TVec2<f32>(x, y));

    if (screenBounds.getWidth() >= mTextureWidth && screenBounds.getHeight() >= mTextureHeight) {
        Mtx m;
        MTXConcat(*pMtx, mDrawMtx, m);
        GXLoadPosMtxImm(m, GX_PNMTX0);
        draw_private(screenBounds, mWindowBox);
    }

    clip(mWindowBox);
}

/* 802D2288-802D2550       .text drawContents__9J2DWindowFRCQ29JGeometry8TBox2<f> */
void J2DWindow::drawContents(const JGeometry::TBox2<f32>& contentsBox) {
    if (contentsBox.isValid()) {
        GXSetNumChans(1);
        GXSetNumTexGens(0);
        GXSetNumTevStages(1);
        GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
        GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
        if ((mColorTL & 0xFF) == 0xFF && (mColorTR & 0xFF) == 0xFF && (mColorBL & 0xFF) == 0xFF && (mColorBR & 0xFF) == 0xFF && mDrawAlpha == 0xFF) {
            GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);
        } else {
            GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
        }

        GXClearVtxDesc();
        GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
        GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);

        JUtility::TColor drawColorTL = mColorTL;
        JUtility::TColor drawColorBL = mColorBL;
        JUtility::TColor drawColorTR = mColorTR;
        JUtility::TColor drawColorBR = mColorBR;
        if (mDrawAlpha != 0xFF) {
            drawColorTL.a = (drawColorTL.a * mDrawAlpha) / 0xFF;
            drawColorBL.a = (drawColorBL.a * mDrawAlpha) / 0xFF;
            drawColorTR.a = (drawColorTR.a * mDrawAlpha) / 0xFF;
            drawColorBR.a = (drawColorBR.a * mDrawAlpha) / 0xFF;
        }

        GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
        GXBegin(GX_QUADS, GX_VTXFMT0, 4);
        GXPosition3f32(contentsBox.i.x, contentsBox.i.y, 0.0f);
        GXColor1u32(drawColorTL);
        GXPosition3f32(contentsBox.f.x, contentsBox.i.y, 0.0f);
        GXColor1u32(drawColorTR);
        GXPosition3f32(contentsBox.f.x, contentsBox.f.y, 0.0f);
        GXColor1u32(drawColorBR);
        GXPosition3f32(contentsBox.i.x, contentsBox.f.y, 0.0f);
        GXColor1u32(drawColorBL);
        GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);

        if (mpContentsTexture != NULL) {
            GXClearVtxDesc();
            GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
            GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
            GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
            GXSetNumTexGens(1);
            drawContentsTexture(contentsBox.i.x, contentsBox.i.y, contentsBox.getWidth(), contentsBox.getHeight());
        }
    }
}

/* 802D2550-802D26E4       .text drawFrameTexture__9J2DWindowFP10JUTTextureffffUsUsUsUsb */
void J2DWindow::drawFrameTexture(JUTTexture* pTexture, f32 x0, f32 y0, f32 w, f32 h, u16 s0, u16 t0, u16 s1, u16 t1, bool bSetupTev) {
    f32 x1 = x0 + w;
    f32 y1 = y0 + h;

    if (bSetupTev) {
        pTexture->load(GX_TEXMAP0);
        setTevMode(pTexture, mBlack, mWhite);
    }

    JUtility::TColor vtxColor(mDrawAlpha | 0xFFFFFF00);

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXBegin(GX_QUADS, GX_VTXFMT0, 4);

    GXPosition3f32(x0, y0, 0.0f);
    GXColor1u32(vtxColor);
    GXTexCoord2s16(s1, t1);

    GXPosition3f32(x1, y0, 0.0f);
    GXColor1u32(vtxColor);
    GXTexCoord2s16(s0, t1);

    GXPosition3f32(x1, y1, 0.0f);
    GXColor1u32(vtxColor);
    GXTexCoord2s16(s0, t0);

    GXPosition3f32(x0, y1, 0.0f);
    GXColor1u32(vtxColor);
    GXTexCoord2s16(s1, t0);

    GXEnd();
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
}

/* 802D26E4-802D2784       .text drawFrameTexture__9J2DWindowFP10JUTTextureffbbb */
void J2DWindow::drawFrameTexture(JUTTexture* pTexture, f32 x, f32 y, bool flipS, bool flipT, bool bSetupTev) {
    /* Nonmatching */
    drawFrameTexture(pTexture, x, y, pTexture->getWidth(), pTexture->getHeight(),
        flipS ? (u16)0 : (u16)0x8000,
        flipT ? (u16)0 : (u16)0x8000,
        flipS ? (u16)0x8000 : (u16)0,
        flipT ? (u16)0x8000 : (u16)0,
        bSetupTev);
}

/* 802D2784-802D29F4       .text drawContentsTexture__9J2DWindowFffff */
void J2DWindow::drawContentsTexture(f32 x0, f32 y0, f32 w, f32 h) {
    f32 x1 = x0 + w;
    f32 y1 = y0 + h;

    f32 texW = mpContentsTexture->getWidth();
    f32 texH = mpContentsTexture->getHeight();
    f32 s0 = -(w / texW - 1.0f) / 2.0f;
    f32 t0 = -(h / texH - 1.0f) / 2.0f;
    f32 s1 = s0 + w / texW;
    f32 t1 = t0 + h / texH;

    mpContentsTexture->load(GX_TEXMAP0);
    setTevMode(mpContentsTexture, 0x00000000, 0xFFFFFFFF);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA6, 0);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXBegin(GX_QUADS, GX_VTXFMT0, 4);

    GXPosition3f32(x0, y0, 0.0f);
    GXColor1u32(mDrawAlpha | 0xFFFFFF00);
    GXTexCoord2f32(s0, t0);

    GXPosition3f32(x1, y0, 0.0f);
    GXColor1u32(mDrawAlpha | 0xFFFFFF00);
    GXTexCoord2f32(s1, t0);

    GXPosition3f32(x1, y1, 0.0f);
    GXColor1u32(mDrawAlpha | 0xFFFFFF00);
    GXTexCoord2f32(s1, t1);

    GXPosition3f32(x0, y1, 0.0f);
    GXColor1u32(mDrawAlpha | 0xFFFFFF00);
    GXTexCoord2f32(s0, t1);

    GXEnd();

    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U16, 0xf);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
}

static inline void GXSetTexCoordGen(GXTexCoordID dst, GXTexGenType type, GXTexGenSrc src, u32 mtx) {
    GXSetTexCoordGen2(dst, type, src, mtx, GX_FALSE, GX_PTIDENTITY);
}

/* 802D29F4-802D2D8C       .text setTevMode__9J2DWindowFP10JUTTextureQ28JUtility6TColorQ28JUtility6TColor */
void J2DWindow::setTevMode(JUTTexture* pTexture, JUtility::TColor reg0, JUtility::TColor reg1) {
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);

    if (mDrawAlpha == 0xFF && reg0 == 0x00000000 && reg1 == 0xFFFFFFFF) {
        s32 alphaEn = pTexture->getTransparency();
        GXSetNumTevStages(1);
        if (mpPalette != NULL)
            alphaEn = mpPalette->getTransparency();

        if (alphaEn == 0) {
            GXSetTevColor(GX_TEVREG2, JUtility::TColor(0xFFFFFFFF));
            GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
            GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
            GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);
        } else {
            GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
            GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
        }
    } else {
        u8 tevStageNum = 1;
        GXSetTevColor(GX_TEVREG2, JUtility::TColor(0xFFFFFFFF));
        GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
        if (pTexture->getTransparency())
            GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
        else
            GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
        GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
        GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);

        if (reg0 != 0x00000000 || reg1 != 0xFFFFFFFF) {
            GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
            GXSetTevColor(GX_TEVREG0, reg0);
            GXSetTevColor(GX_TEVREG1, reg1);
            GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_C0, GX_CC_C1, GX_CC_CPREV, GX_CC_ZERO);
            GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_A0, GX_CA_A1, GX_CA_APREV, GX_CA_ZERO);
            GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            tevStageNum = 2;
        }

        if (mDrawAlpha != 0xFF) {
            GXSetTevOrder((GXTevStageID)(GX_TEVSTAGE0 + tevStageNum), GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
            GXSetTevColorIn((GXTevStageID)(GX_TEVSTAGE0 + tevStageNum), GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
            GXSetTevAlphaIn((GXTevStageID)(GX_TEVSTAGE0 + tevStageNum), GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO);
            GXSetTevColorOp((GXTevStageID)(GX_TEVSTAGE0 + tevStageNum), GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            GXSetTevAlphaOp((GXTevStageID)(GX_TEVSTAGE0 + tevStageNum), GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
            tevStageNum++;
        }

        GXSetNumTevStages(tevStageNum);
        GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET);
    }

    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
}
