/*
 The shop is where the player can buy cards, decks...
 */
#include "PrecompiledHeader.h"

#include <JRenderer.h>
#include "GameStateShop.h"
#include "GameApp.h"
#include "MTGDeck.h"
#include "MTGPack.h"
#include "Translate.h"
#include "TestSuiteAI.h"

#include <hge/hgedistort.h>
#include "WFont.h"

float GameStateShop::_x1[] = { 79, 19, 27, 103, 154, 187, 102, 144, 198, 133, 183 };
float GameStateShop::_y1[] = { 150, 194, 222, 167, 164, 156, 195, 190, 175, 220, 220 };

float GameStateShop::_x2[] = { 103, 48, 74, 135, 183, 215, 138, 181, 231, 171, 225 };
float GameStateShop::_y2[] = { 155, 179, 218, 165, 166, 155, 195, 186, 177, 225, 216 };

float GameStateShop::_x3[] = { 48, 61, 9, 96, 139, 190, 81, 146, 187, 97, 191 };
float GameStateShop::_y3[] = { 164, 205, 257, 184, 180, 170, 219, 212, 195, 251, 252 };

float GameStateShop::_x4[] = { 76, 90, 65, 131, 171, 221, 123, 187, 225, 141, 237 };
float GameStateShop::_y4[] = { 169, 188, 250, 182, 182, 168, 220, 208, 198, 259, 245 };

namespace
{
#ifndef TOUCH_ENABLED
    float kPspIconScaleFactor = 0.5f;
#endif // TOUCH_ENABLED
    std::string kOtherCardsString(": Other cards");
    std::string kCreditsString("Credits: ");
}


BoosterDisplay::BoosterDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener, TargetChooser * tc,
                int nb_displayed_items) :
    CardDisplay(id, game, x, y, listener, tc, nb_displayed_items)
{
}

bool BoosterDisplay::CheckUserInput(JButton key)
{
    if (JGE_BTN_UP == key || JGE_BTN_DOWN == key || JGE_BTN_PRI == key)
        return false;

    return CardDisplay::CheckUserInput(key);

}

GameStateShop::GameStateShop(GameApp* parent) :
    GameState(parent, "shop")
{
    menu = NULL;
    boosterDisplay = NULL;
    taskList = NULL;
    srcCards = NULL;
    shopMenu = NULL;
    bigDisplay = NULL;
    myCollection = NULL;
    packlist = NULL;
    pricelist = NULL;
    playerdata = NULL;
    booster = NULL;
    lightAlpha = 0;
    filterMenu = NULL;
    alphaChange = 0;
    for (int i = 0; i < SHOP_ITEMS; i++)
    {
        mPrices[i] = 0;
        mCounts[i] = 0;
    }
    mTouched = false;

    kOtherCardsString = _(kOtherCardsString);
    kCreditsString = _(kCreditsString);
    
    cycleCardsButton = NEW InteractiveButton(NULL, kCycleCardsButtonId, Fonts::MAIN_FONT, "New Cards", SCREEN_WIDTH_F - 80, SCREEN_HEIGHT_F - 20, JGE_BTN_PRI);
    
    showCardListButton = NEW InteractiveButton(NULL, kShowCardListButtonId, Fonts::MAIN_FONT, "Show List", SCREEN_WIDTH_F - 150, SCREEN_HEIGHT_F - 20, JGE_BTN_SEC);
    disablePurchase = false;
    clearInput = false;
}

GameStateShop::~GameStateShop()
{
    SAFE_DELETE( cycleCardsButton );
    SAFE_DELETE( showCardListButton );
    End();
}

void GameStateShop::Create()
{
}

void GameStateShop::Start()
{
    menu = NULL;
    bListCards = false;
    mTouched = false;
    mStage = STAGE_FADE_IN;
    needLoad = true;
    booster = NULL;
    srcCards = NEW WSrcUnlockedCards(0);
    srcCards->setElapsed(15);
    srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T")));
    srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET)));

    shopMenu = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, true, &bigSync);
    MTGAllCards * ac = MTGCollection();
    playerdata = NEW PlayerData(ac);
    myCollection = NEW DeckDataWrapper(playerdata->collection);
    pricelist = NEW PriceList("settings/prices.dat", ac);
    for (int i = 0; i < SHOP_SLOTS; i++)
    {
        WGuiCardDistort * dist;
        if (i < BOOSTER_SLOTS)
            dist = NEW WGuiCardDistort(NULL, true);
        else
        {
            dist = NEW WGuiCardDistort(srcCards, true);
            dist->mOffset.setOffset(i - BOOSTER_SLOTS);
        }
        dist->xy = WDistort(_x1[i], _y1[i], _x2[i], _y2[i], _x3[i], _y3[i], _x4[i], _y4[i]);
        shopMenu->Add(NEW WGuiButton(dist, -102, i, this));
    }
    shopMenu->Entering(JGE_BTN_NONE);

    if (!bigDisplay)
    {
        bigDisplay = NEW WGuiCardImage(srcCards);
        bigDisplay->mOffset.Hook(&bigSync);
        bigDisplay->mOffset.setOffset(-BOOSTER_SLOTS);
        bigDisplay->setX(385);
        bigDisplay->setY(135);
    }

    for (int i = 0; i < 8; ++i)
    {
        std::ostringstream stream;
        stream << "iconspsp" << i;
        pspIcons[i] = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, stream.str(), RETRIEVE_MANAGE);
        pspIcons[i]->SetHotSpot(16, 16);
    }

    JRenderer::GetInstance()->EnableVSync(true);

    taskList = NULL;
    packlist = NEW MTGPacks();
    packlist->loadAll();
    load();
}

string GameStateShop::descPurchase(int controlId, bool tiny)
{
    char buffer[4096];
    string name;
    if (controlId < BOOSTER_SLOTS)
    {
        name = mBooster[controlId].getName();
    }
    else
    {
        MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS);
        if (!c)
            return "";
        name = _(c->data->getName());
    }
    if (mInventory[controlId] <= 0)
    {
        if (tiny)
            sprintf(buffer, _("SOLD OUT").c_str(), name.c_str());
        else
            sprintf(buffer, _("%s : SOLD OUT").c_str(), name.c_str());
        return buffer;
    }

    if (tiny)
    {
        if (controlId < BOOSTER_SLOTS || mCounts[controlId] == 0)
            return name;

        sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]);
        return buffer;
    }
    switch (options[Options::ECON_DIFFICULTY].number)
    {
    case Constants::ECON_HARD:
    case Constants::ECON_NORMAL:
        if (mCounts[controlId] < 1)
            sprintf(buffer, _("%s").c_str(), name.c_str());
        else
            sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]);
        break;
    default:
        if (mCounts[controlId] < 1)
            sprintf(buffer, _("%s : %i credits").c_str(), name.c_str(), mPrices[controlId]);
        else
            sprintf(buffer, _("%s (%i) : %i credits").c_str(), name.c_str(), mCounts[controlId], mPrices[controlId]);
        break;
    }
    return buffer;
}
void GameStateShop::beginPurchase(int controlId)
{
    WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MENU_FONT);
    mFont->SetScale(SCALE_NORMAL);
    SAFE_DELETE(menu);
    if (mInventory[controlId] <= 0)
    {
        menu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Sold Out").c_str());
        menu->Add(-1, "Ok");
    }
    else if (playerdata->credits - mPrices[controlId] < 0)
    {
        menu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Not enough credits").c_str());
        menu->Add(-1, "Ok");
        if (options[Options::CHEATMODE].number)
        {
            menu->Add(-2, _("Steal it").c_str());
        }
    }
    else
    {
        char buf[512];
        if (controlId < BOOSTER_SLOTS)
            sprintf(buf, _("Purchase Booster: %i credits").c_str(), mPrices[controlId]);
        else
            sprintf(buf, _("Purchase Card: %i credits").c_str(), mPrices[controlId]);
        menu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, buf);

        menu->Add(controlId, "Yes");
        menu->Add(-1, "No");
    }
}
void GameStateShop::cancelCard(int controlId)
{
    //Update prices
    MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS);
    if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0)
        return; //We only care about their opinion if they /can/ buy it.

    int price = mPrices[controlId];
    int rnd;
    switch (options[Options::ECON_DIFFICULTY].number)
    {
    case Constants::ECON_HARD:
        rnd = rand() % 10;
        break;
    case Constants::ECON_EASY:
        rnd = rand() % 50;
        break;
    default:
        rnd = rand() % 25;
        break;
    }
    price = price - (rnd * price) / 100;
    if (price < pricelist->getPrice(c)) //filters have a tendancy to increase the price instead of lowering it!
        pricelist->setPrice(c, price);
    //Prices do not immediately go down when you ignore something.
    return;
}
void GameStateShop::cancelBooster(int)
{
    return; //TODO FIXME Tie boosters into pricelist.
}
void GameStateShop::purchaseCard(int controlId)
{
    MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS);
    if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0)
        return;
    myCollection->Add(c);
    int price = mPrices[controlId];
    pricelist->setPrice(c->getMTGId(), price); // In case they changed their minds after cancelling.
    playerdata->credits -= price;
    //Update prices
    int rnd;
    switch (options[Options::ECON_DIFFICULTY].number)
    {
    case Constants::ECON_HARD:
        rnd = rand() % 50;
        break;
    case Constants::ECON_EASY:
        rnd = rand() % 10;
        break;
    default:
        rnd = rand() % 25;
        break;
    }
    price = price + (rnd * price) / 100;
    pricelist->setPrice(c->getMTGId(), price);
    mPrices[controlId] = pricelist->getPurchasePrice(c->getMTGId()); //Prices go up immediately.
    mInventory[controlId]--;
    updateCounts();
    mTouched = true;
    menu->Close();
}
void GameStateShop::purchaseBooster(int controlId)
{
    if (playerdata->credits - mPrices[controlId] < 0)
        return;
    playerdata->credits -= mPrices[controlId];
    mInventory[controlId]--;
    SAFE_DELETE(booster);
    deleteDisplay();
    booster = NEW MTGDeck(MTGCollection());
    boosterDisplay = NEW BoosterDisplay(12, NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT / 2, this, NULL, 5);
    mBooster[controlId].addToDeck(booster, srcCards);

    string sort = mBooster[controlId].getSort();
    DeckDataWrapper * ddw = NEW DeckDataWrapper(booster);
    if (sort == "alpha")
        ddw->Sort(WSrcCards::SORT_ALPHA);
    else if (sort == "collector")
        ddw->Sort(WSrcCards::SORT_COLLECTOR);
    else
        ddw->Sort(WSrcCards::SORT_RARITY);

    for (int x = 0; x < ddw->Size(); x++)
    {
        MTGCard * c = ddw->getCard(x);
        for (int copies = 0; copies < ddw->count(c); ++copies)
        {
            MTGCardInstance * ci = NEW MTGCardInstance(c, NULL);
            boosterDisplay->AddCard(ci);
            subBooster.push_back(ci);
        }
    }
    SAFE_DELETE(ddw);

    myCollection->loadMatches(booster);
    mTouched = true;
    save(true);
    menu->Close();
}

int GameStateShop::purchasePrice(int offset)
{
    MTGCard * c = NULL;
    if (!pricelist || !srcCards || (c = srcCards->getCard(offset)) == NULL)
        return 0;
    float price = (float) pricelist->getPurchasePrice(c->getMTGId());
    int filteradd = srcCards->Size(true);
    filteradd = ((filteradd - srcCards->Size()) / filteradd);

    switch (options[Options::ECON_DIFFICULTY].number)
    {
    case Constants::ECON_EASY:
        filteradd /= 2;
        break;
    case Constants::ECON_HARD:
        filteradd *= 2;
        break;
    default:
        break;
    }
    return (int) (price + price * (filteradd * srcCards->filterFee()));
}
void GameStateShop::updateCounts()
{
    for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++)
    {
        MTGCard * c = srcCards->getCard(i - BOOSTER_SLOTS);
        if (!c)
            mCounts[i] = 0;
        else
            mCounts[i] = myCollection->countByName(c);
    }
}
void GameStateShop::load()
{
    for (int i = 0; i < BOOSTER_SLOTS; i++)
    {
        mBooster[i].randomize(packlist);
        mInventory[i] = 1 + rand() % mBooster[i].maxInventory();
        mPrices[i] = pricelist->getOtherPrice(mBooster[i].basePrice());
    }
    for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++)
    {
        MTGCard * c = NULL;
        if ((c = srcCards->getCard(i - BOOSTER_SLOTS)) == NULL)
        {
            mPrices[i] = 0;
            mCounts[i] = 0;
            mInventory[i] = 0;
            continue;
        }
        mPrices[i] = purchasePrice(i - BOOSTER_SLOTS);
        mCounts[i] = myCollection->countByName(c);
        switch (c->getRarity())
        {
        case Constants::RARITY_C:
            mInventory[i] = 2 + rand() % 8;
            break;
        case Constants::RARITY_L:
            mInventory[i] = 100;
            break;
        default: //We're using some non-coded rarities (S) in cards.dat.
        case Constants::RARITY_U:
            mInventory[i] = 1 + rand() % 5;
            break;
        case Constants::RARITY_R:
            mInventory[i] = 1 + rand() % 2;
            break;
        }

    }
}
void GameStateShop::save(bool force)
{
    if (mTouched || force)
    {
        if (myCollection)
            myCollection->Rebuild(playerdata->collection);
        if (playerdata)
            playerdata->save();
        if (pricelist)
            pricelist->save();
    }
    mTouched = false;
}
void GameStateShop::End()
{
    save();
    JRenderer::GetInstance()->EnableVSync(false);

    SAFE_DELETE(shopMenu);
    SAFE_DELETE(bigDisplay);
    SAFE_DELETE(srcCards);
    SAFE_DELETE(playerdata);
    SAFE_DELETE(pricelist);
    SAFE_DELETE(myCollection);
    SAFE_DELETE(booster);
    SAFE_DELETE(filterMenu);
    SAFE_DELETE(packlist);
    deleteDisplay();

    SAFE_DELETE(menu);
    SAFE_DELETE(taskList);
}

void GameStateShop::Destroy()
{
}
void GameStateShop::beginFilters()
{
    if (!filterMenu)
    {
        filterMenu = NEW WGuiFilters("Ask about...", srcCards);
        filterMenu->setY(2);
        filterMenu->setHeight(SCREEN_HEIGHT - 2);
    }
    mStage = STAGE_ASK_ABOUT;
    filterMenu->Entering(JGE_BTN_NONE);
}
void GameStateShop::Update(float dt)
{
    if (menu && menu->isClosed())
        SAFE_DELETE(menu);
    srcCards->Update(dt);
    alphaChange = 25 - static_cast<int>((float) (rand() - 1) / (RAND_MAX) * 50.0f);
    lightAlpha += alphaChange;
    if (lightAlpha < 0)
        lightAlpha = 0;
    if (lightAlpha > 50)
        lightAlpha = 50;

    JButton btn;
    switch (mStage)
    {
    case STAGE_SHOP_PURCHASE:
        if (menu)
            menu->Update(dt);
        beginPurchase(mBuying);
        mStage = STAGE_SHOP_SHOP;
        break;
    case STAGE_SHOP_MENU:
        if (menu)
            menu->Update(dt);
        else
        {
            menu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), 11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20);
            menu->Add(22, _("Ask about...").c_str());
            menu->Add(14, _("Check task board").c_str());
            if (options[Options::CHEATMODE].number)
                menu->Add(-2, _("Steal 1,000 credits").c_str());
            menu->Add(12, _("Save And Exit").c_str());
            menu->Add(kCancelMenuID, _("Cancel").c_str());
        }
        break;
    case STAGE_SHOP_TASKS:
        if (menu && !menu->isClosed())
        {
            menu->Update(dt);
            return;
        }
        if (taskList)
        {
            btn = mEngine->ReadButton();
            taskList->Update(dt);
            if (taskList->getState() != TaskList::TASKS_INACTIVE)
            {
                if (btn == JGE_BTN_SEC || btn == JGE_BTN_CANCEL || btn == JGE_BTN_PREV)
                {
                    taskList->End();
                    return;
                }
                else if (taskList->getState() == TaskList::TASKS_ACTIVE && btn == JGE_BTN_MENU)
                {
                    if (!menu)
                    {
                        menu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), 11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20);
                        menu->Add(15, "Return to shop");
                        menu->Add(12, "Save And Exit");
                        menu->Add(kCancelMenuID, "Cancel");
                    }
                }
            }
            else
                mStage = STAGE_SHOP_SHOP;
        }

#ifdef TESTSUITE
        if ((mEngine->GetButtonClick(JGE_BTN_PRI)) && (taskList))
        {
            taskList->passOneDay();
            if (taskList->getTaskCount() < 6)
            {
                taskList->addRandomTask();
                taskList->addRandomTask();
            }
            taskList->save();
        }
#endif
        break;
    case STAGE_ASK_ABOUT:
        btn = mEngine->ReadButton();
        if (menu && !menu->isClosed())
        {
            menu->CheckUserInput(btn);
            menu->Update(dt);
            return;
        }
        if (filterMenu)
        {
            if (btn == JGE_BTN_CTRL)
            {
                needLoad = filterMenu->Finish();
                filterMenu->Update(dt);
                return;
            }
            if (filterMenu->isFinished())
            {
                if (needLoad)
                {
                    srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T")));
                    srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET)));
                    if (!srcCards->Size())
                    {
                        srcCards->clearFilters(); //Repetition of check at end of filterMenu->Finish(), for the token removal
                        srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T")));
                        srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET)));
                    }
                    load();
                }
                mStage = STAGE_SHOP_SHOP;
            }
            else
            {
                filterMenu->CheckUserInput(btn);
                filterMenu->Update(dt);
            }
            return;
        }
        break;
    case STAGE_SHOP_SHOP:
        btn = mEngine->ReadButton();
        if (menu && !menu->isClosed())
        {
            menu->CheckUserInput(btn);
            menu->Update(dt);
            return;
        }
        if (btn == JGE_BTN_MENU)
        {
            if (boosterDisplay)
            {
                deleteDisplay();
                return;
            }
            mStage = STAGE_SHOP_MENU;
            return;
        }
        else if (btn == JGE_BTN_CTRL)
            beginFilters();
        else if (btn == JGE_BTN_NEXT)
        {
            mStage = STAGE_SHOP_TASKS;
            if (!taskList)
                taskList = NEW TaskList();
            taskList->Start();
        }
        else if (boosterDisplay)
        {
            if (btn == JGE_BTN_SEC)
                deleteDisplay();
            else
            {
                boosterDisplay->CheckUserInput(btn);
                boosterDisplay->Update(dt);
            }
            return;
        }
        else if (btn == JGE_BTN_PRI) // so we don't shuffle while we view our newly purchased booster display.
        {
            srcCards->Shuffle();
            load();
            disablePurchase = false;
            clearInput = true;
            return;

        }
        else if (btn == JGE_BTN_CANCEL)
            options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number;
        else if (btn == JGE_BTN_SEC)
		{
            bListCards = !bListCards;
            disablePurchase = false;
            clearInput = true;
            return;
		}
        else if (shopMenu)
        {
#if defined (IOS) || defined (ANDROID)
            if ((cycleCardsButton->ButtonPressed() || showCardListButton->ButtonPressed()))
#else 
            if ( (btn == JGE_BTN_OK) && (cycleCardsButton->ButtonPressed() || showCardListButton->ButtonPressed()))
#endif
            {
                disablePurchase = true;
                return;
            }
            else 
#if defined (IOS) || defined (ANDROID)
                if (clearInput && (btn == JGE_BTN_OK))
                {
                    clearInput = false;
                    disablePurchase = false;
                    return;
                }
            else
#endif
                if (shopMenu->CheckUserInput(btn))
                    srcCards->Touch();
        }
        if (shopMenu)
            shopMenu->Update(dt);

        break;
    case STAGE_FADE_IN:
        mParent->DoAnimation(TRANSITION_FADE_IN);
        mStage = STAGE_SHOP_SHOP;
        break;
    }
}

void GameStateShop::deleteDisplay()
{
    vector<MTGCardInstance*>::iterator i;
    for (i = subBooster.begin(); i != subBooster.end(); i++)
    {
        if (!*i)
            continue;
        delete *i;
    }
    subBooster.clear();
    SAFE_DELETE(boosterDisplay);
}

void GameStateShop::enableButtons()
{
    cycleCardsButton->setIsSelectionValid(true);
    showCardListButton->setIsSelectionValid(true);
}

void GameStateShop::renderButtons()
{
    cycleCardsButton->Render();
    showCardListButton->Render();
}

void GameStateShop::Render()
{
    //Erase
    WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
    JRenderer * r = JRenderer::GetInstance();
    r->ClearScreen(ARGB(0,0,0,0));
    if (mStage == STAGE_FADE_IN)
        return;

    JQuadPtr mBg = WResourceManager::Instance()->RetrieveTempQuad("shop.jpg", TEXTURE_SUB_5551);
    if (mBg.get())
        r->RenderQuad(mBg.get(), 0, 0);

    JQuadPtr quad = WResourceManager::Instance()->RetrieveTempQuad("shop_light.jpg", TEXTURE_SUB_5551);
    if (quad.get())
    {
        r->EnableTextureFilter(false);
        r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);
        quad->SetColor(ARGB(lightAlpha,255,255,255));
        r->RenderQuad(quad.get(), 0, 0);
        r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
        r->EnableTextureFilter(true);
    }

    if (shopMenu)
        shopMenu->Render();
    
    if (filterMenu && !filterMenu->isFinished())
        filterMenu->Render();
    else
    {
        if (boosterDisplay)
            boosterDisplay->Render();
        else if (bigDisplay)
        {
            if (bigDisplay->mOffset.getPos() >= 0)
                bigDisplay->setSource(srcCards);
            else
                bigDisplay->setSource(NULL);
            bigDisplay->Render();
            float elp = srcCards->getElapsed();
            //Render the card list overlay.
            if (bListCards || elp > LIST_FADEIN)
            {
                int alpha = 200;
                if (!bListCards && elp < LIST_FADEIN + .25)
                {
                    alpha = static_cast<int> (800 * (elp - LIST_FADEIN));
                }
                r->FillRoundRect(300, 10, 160, SHOP_SLOTS * 20 + 15, 5, ARGB(alpha,0,0,0));
                alpha += 55;
                for (int i = 0; i < SHOP_SLOTS; i++)
                {
                    if (i == shopMenu->getSelected())
                        mFont->SetColor(ARGB(alpha,255,255,0));
                    else
                        mFont->SetColor(ARGB(alpha,255,255,255));
                    char buffer[512];
                    string s = descPurchase(i, true);
                    sprintf(buffer, "%s", s.c_str());
                    float x = 310;
                    float y = static_cast<float> (25 + 20 * i);
                    mFont->DrawString(buffer, x, y);
                }
            }
        }
    }

    //Render the info bar
    r->FillRect(0, SCREEN_HEIGHT - 17, SCREEN_WIDTH, 17, ARGB(128,0,0,0));
    std::ostringstream stream;
    stream << kCreditsString << playerdata->credits;
    mFont->SetColor(ARGB(255,255,255,255));
    mFont->DrawString(stream.str(), 5, SCREEN_HEIGHT - 14);

#ifndef TOUCH_ENABLED
    float len = 4 + mFont->GetStringWidth(kOtherCardsString.c_str());
	r->RenderQuad(pspIcons[6].get(), SCREEN_WIDTH - len - 0.5 - 10, SCREEN_HEIGHT - 8, 0, kPspIconScaleFactor, kPspIconScaleFactor);
    mFont->DrawString(kOtherCardsString, SCREEN_WIDTH - len, SCREEN_HEIGHT - 14);
#else
    enableButtons();
#endif
    
    mFont->SetColor(ARGB(255,255,255,0));
    mFont->DrawString(descPurchase(bigSync.getPos()).c_str(), SCREEN_WIDTH / 2, SCREEN_HEIGHT - 14, JGETEXT_CENTER);
    mFont->SetColor(ARGB(255,255,255,255));

    if (mStage == STAGE_SHOP_TASKS && taskList)
    {
        taskList->Render();
    }
    if (menu)
        menu->Render();
    
    if (!filterMenu || (filterMenu && filterMenu->isFinished()))
        renderButtons();
}

void GameStateShop::ButtonPressed(int controllerId, int controlId)
{
    int sel = bigSync.getOffset();
    switch (controllerId)
    {
    case -102: //Buying something...
        mStage = STAGE_SHOP_PURCHASE;
        if (menu)
            menu->Close();
        mBuying = controlId;
        return;
    case -145:
        if (controlId == -1)
        { //Nope, don't buy.
            if (sel < BOOSTER_SLOTS)
                cancelBooster(sel);
            else
                cancelCard(sel);
            menu->Close();
            mStage = STAGE_SHOP_SHOP;
            return;
        }
        if (sel > -1 && sel < SHOP_ITEMS)
        {
            if (controlId == -2)
                playerdata->credits += mPrices[sel]; //We stole it.
            if (sel < BOOSTER_SLOTS) //Clicked a booster.
                purchaseBooster(sel);
            else
                purchaseCard(sel);

            //Check if we just scored an award...
            if (myCollection && myCollection->totalPrice() > 10000)
            {
                GameOptionAward * goa = dynamic_cast<GameOptionAward *> (&options[Options::AWARD_COLLECTOR]);
                if (goa) goa->giveAward();
            }
        }
        mStage = STAGE_SHOP_SHOP;
        return;
    }
    //Basic Menu.
    switch (controlId)
    {
    case 12:
        if (taskList)
            taskList->save();
        mStage = STAGE_SHOP_SHOP;
        mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU);
        save();
        break;
    case 14:
        mStage = STAGE_SHOP_TASKS;
        if (!taskList)
            taskList = NEW TaskList();
        taskList->Start();
        break;
    case 15:
        if (taskList)
            taskList->End();
        break;
    case 22:
        beginFilters();
        break;
    case -2:
        playerdata->credits += 1000;
    default:
        mStage = STAGE_SHOP_SHOP;
    }
    menu->Close();
}

void GameStateShop::OnScroll(int inXVelocity, int)
{
    // we ignore magnitude since there isn't any scrolling in the shop
    if (abs(inXVelocity) > 200)
    {
        bool flickRight = (inXVelocity >= 0);
        if (flickRight)
            mEngine->HoldKey_NoRepeat(JGE_BTN_PRI);
    }
}

//ShopBooster
ShopBooster::ShopBooster()
{
    pack = NULL;
    mainSet = NULL;
    altSet = NULL;
}
string ShopBooster::getSort()
{
    if (pack)
        return pack->getSort();
    return "";
}
;
string ShopBooster::getName()
{
    char buffer[512];
    if (!mainSet && pack)
        return pack->getName();
    if (altSet == mainSet)
        altSet = NULL;
    if (altSet)
        sprintf(buffer, _("%s & %s (15 Cards)").c_str(), mainSet->id.c_str(), altSet->id.c_str());
    else if (mainSet)
        sprintf(buffer, _("%s Booster (15 Cards)").c_str(), mainSet->id.c_str());
    return buffer;
}

void ShopBooster::randomize(MTGPacks * packlist)
{
    mainSet = NULL;
    altSet = NULL;
    pack = NULL;
    if (!setlist.size())
        return;
    if (packlist && setlist.size() > 10)
    { //FIXME make these an unlockable item.
        int rnd = rand() % 100;
        if (rnd <= Constants::CHANCE_CUSTOM_PACK)
        {
            randomCustom(packlist);
            return;
        }
    }
    randomStandard();
}
int ShopBooster::basePrice()
{
    if (pack)
        return pack->getPrice();
    else if (altSet)
        return Constants::PRICE_MIXED_BOOSTER;
    return Constants::PRICE_BOOSTER;
}
void ShopBooster::randomCustom(MTGPacks * packlist)
{
    pack = packlist->randomPack();
    if (pack && !pack->isUnlocked())
        pack = NULL;
    if (!pack)
        randomStandard();
}
void ShopBooster::randomStandard()
{

    MTGSetInfo * si = setlist.randomSet(-1);
    mainSet = si;
    altSet = NULL;

    int mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS];
    if (mSetCount < 80)
    {
        if (rand() % 100 < Constants::CHANCE_PURE_OVERRIDE)
        { //Chance of picking a pure pack instead.
            si = setlist.randomSet(-1, 80);
            mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS];
            mainSet = si;
        }
        else
            altSet = setlist.randomSet(si->block, 80 - mSetCount);
    }
    else if (rand() % 100 < Constants::CHANCE_MIXED_OVERRIDE) //Chance of having a mixed booster anyways.
        altSet = setlist.randomSet(si->block);

    for (int attempts = 0; attempts < 10; attempts++)
    { //Try to prevent altSet == mainSet.
        if (altSet != mainSet)
            break;
        altSet = setlist.randomSet(-1, 80 - mSetCount);
    }
    if (altSet == mainSet)
        altSet = NULL; //Prevent "10E & 10E Booster"
    if (!altSet)
        pack = mainSet->mPack;

}
int ShopBooster::maxInventory()
{
    if (altSet || pack)
        return 2;
    return 5;
}
void ShopBooster::addToDeck(MTGDeck * d, WSrcCards *)
{
    if (!pack)
    { //A combination booster.
        MTGPack * mP = MTGPacks::getDefault();
        if (!altSet && mainSet->mPack)
            mP = mainSet->mPack;
        char buf[512];
        if (!altSet)
            sprintf(buf, "set:%s;", mainSet->id.c_str());
        else
            sprintf(buf, "set:%s;|set:%s;", mainSet->id.c_str(), altSet->id.c_str());
        mP->pool = buf;
        mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool.
    }
    else
        pack->assemblePack(d);
}

#ifdef TESTSUITE
bool ShopBooster::unitTest()
{
    //this tests the default random pack creation.
    MTGDeck * d = NEW MTGDeck(MTGCollection());
    char result[1024];

    randomStandard();
    MTGPack * mP = MTGPacks::getDefault();
    if(!altSet && mainSet->mPack) mP = mainSet->mPack;
    char buf[512];
    if(!altSet) sprintf(buf,"set:%s;",mainSet->id.c_str());
    else sprintf(buf,"set:%s;|set:%s;",mainSet->id.c_str(),altSet->id.c_str());
    mP->pool = buf;
    mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool.
    DeckDataWrapper* ddw = NEW DeckDataWrapper(d);
    bool res = true;

    int u = 0, r = 0, s = 0;
    int card = 0;
    for(int i=0;i<ddw->Size(true);i++)
    {
        MTGCard * c = ddw->getCard(i);
        if(!c) break;
        if(c->getRarity() == Constants::RARITY_R || c->getRarity() == Constants::RARITY_M)
        r+=ddw->count(c);
        else if(c->getRarity() == Constants::RARITY_U)
        u+=ddw->count(c);
        else if(c->getRarity() == Constants::RARITY_S)
        s+=ddw->count(c);
        card++;
    }
    int count = ddw->getCount();
    SAFE_DELETE(ddw);
    SAFE_DELETE(d);
    //Note: When there are special cards, the count IS going to be messed up, so do not perform the check for Rare and Uncommon in that case
    //also see http://code.google.com/p/wagic/issues/detail?id=644
    if(!s && (r != 1 || u != 3) ) 
    {
        sprintf(result, "<span class=\"error\">==Unexpected rarity count==</span><br />");
        TestSuite::Log(result);
        res = false;
    }
    if(count < 14)
    {
        sprintf(result, "<span class=\"error\">==Unexpected card count==</span><br />");
        TestSuite::Log(result);
        res = false;
    }
    sprintf(result, "<span class=\"success\">==Test Succesful !==</span><br />");
    TestSuite::Log(result);
    SAFE_DELETE(ddw);
    SAFE_DELETE(d);
    return res;
}
#endif
