/*
 *  The Mana Client
 *  Copyright (C) 2010  The Mana Developers
 *
 *  This file is part of The Mana Client.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "gui/widgets/avatarlistbox.h"

#include "beingmanager.h"
#include "graphics.h"
#include "localplayer.h"

#include "gui/chat.h"
#include "gui/gui.h"
#include "gui/palette.h"
#include "gui/viewport.h"
#include "gui/theme.h"

#include "resources/image.h"
#include "resources/resourcemanager.h"

#include "utils/stringutils.h"

#include <guichan/font.hpp>

int AvatarListBox::instances = 0;
Image *AvatarListBox::onlineIcon = 0;
Image *AvatarListBox::offlineIcon = 0;

AvatarListBox::AvatarListBox(AvatarListModel *model):
    ListBox(model)
{
    instances++;

    if (instances == 1)
    {
        onlineIcon = Theme::getImageFromTheme("circle-green.png");
        offlineIcon = Theme::getImageFromTheme("circle-gray.png");
    }

    setWidth(200);
}

AvatarListBox::~AvatarListBox()
{
    instances--;

    if (instances == 0)
    {
        if (onlineIcon)
            onlineIcon->decRef();
        if (offlineIcon)
            offlineIcon->decRef();
    }
}

void AvatarListBox::draw(gcn::Graphics *gcnGraphics)
{
    if (!mListModel)
        return;

    AvatarListModel* model = static_cast<AvatarListModel*>(mListModel);

    updateAlpha();

    Graphics *graphics = static_cast<Graphics*>(gcnGraphics);

    graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
                                            (int) (mAlpha * 255.0f)));
    graphics->setFont(getFont());

    const int fontHeight = getFont()->getHeight();

//    int newWidth = 0;
//    int width = 0;

    Widget *parent = getParent();

    // Draw the list elements
    graphics->setColor(Theme::getThemeColor(Theme::TEXT));
    for (int i = 0, y = 0;
         i < model->getNumberOfElements();
         ++i, y += fontHeight)
    {
        Avatar *a = model->getAvatarAt(i);
        if (!a)
            continue;

        // Draw online status
        Image *icon = a->getOnline() ? onlineIcon : offlineIcon;
        if (icon)
            graphics->drawImage(icon, 2, y + 1);

        if (a->getDisplayBold())
            graphics->setFont(boldFont);

        std::string text;

        if (a->getMaxHp() > 0)
        {
            if (a->getLevel() > 1)
            {
                text = strprintf("%s %d/%d (%d)", a->getComplexName().c_str(),
                                 a->getHp(), a->getMaxHp(), a->getLevel());
            }
            else
            {
                text = strprintf("%s %d/%d", a->getComplexName().c_str(),
                                 a->getHp(), a->getMaxHp());
            }
            if (parent)
            {
                gcn::Color color = Theme::getProgressColor(
                        Theme::PROG_HP, a->getHp() / a->getMaxHp());
                color.a = 80;
                graphics->setColor(color);

                graphics->fillRectangle(gcn::Rectangle(0, y,
                        parent->getWidth() * a->getHp() / a->getMaxHp(), fontHeight));
            }
        }
        else if (a->getDamageHp() != 0)
        {
            if (a->getLevel() > 1)
            {
                text = strprintf("%s -%d (%d)", a->getComplexName().c_str(),
                                 a->getDamageHp(), a->getLevel());
            }
            else
            {
                text = strprintf("%s -%d", a->getComplexName().c_str(),
                                 a->getDamageHp());
            }

            if (parent)
            {
//                int diff;
//                if (a->getDamageHp() > 1024)
//                    diff = 0;
//                else
//                    diff = 1024 - a->getDamageHp();
                gcn::Color color = Theme::getProgressColor(Theme::PROG_HP,
                        1);
//                        0 / 1024);
/*
                if (a->getDamageHp() >= 400)
                {
                }
                else
                {
//                    int intens = 1024/(400 - a->getDamageHp());
                    int intens = a->getDamageHp() / 1024;
                    if (intens > 1)
                        intens = 1;
                    color = Theme::getProgressColor(Theme::PROG_HP,
                        intens);
                }
*/

                color.a = 80;
                graphics->setColor(color);
                graphics->fillRectangle(gcn::Rectangle(0, y,
                                                parent->getWidth()*a->getDamageHp()/1024,
                                                fontHeight));

                if (a->getLevel() > 1)
                {
                    graphics->setColor(Theme::getThemeColor(Theme::TEXT));
                    int minHp = 40 + ((a->getLevel() - 1) * 5);
                    if (minHp < 0)
                        minHp = 40;

                    graphics->drawLine(parent->getWidth()*minHp/1024, y,
                                       parent->getWidth()*minHp/1024, y + fontHeight);
                }
            }
        }
        else
        {
            if (a->getLevel() > 1)
            {
                text = strprintf("%s (%d)", a->getComplexName().c_str(),
                                 a->getLevel());
            }
            else
            {
                text = a->getComplexName();
            }
        }

        if (!a->getMap().empty() && a->getOnline())
        {
            if (a->getX() != -1)
                text += strprintf(" [%d,%d %s]", a->getX(), a->getY(), a->getMap().c_str());
            else
                text += strprintf(" [%s]", a->getMap().c_str());
        }

        graphics->setColor(Theme::getThemeColor(Theme::TEXT));

        // Draw Name
        graphics->drawText(text, 15, y);

//        width = graphics->getFont()->getWidth(text) + 17; // Extra right padding

//        if (width > newWidth)
//        {
//            newWidth = width;
//        }

        if (a->getDisplayBold())
            graphics->setFont(getFont());
    }

//    if (parent->getWidth() < newWidth + 10)
//        setWidth(newWidth);
//    else
        setWidth(parent->getWidth() - 10);
}

void AvatarListBox::mousePressed(gcn::MouseEvent &event)
{
    int y = event.getY() / getFont()->getHeight();
    if (!mListModel || y > mListModel->getNumberOfElements())
        return;

    setSelected(y);
    distributeActionEvent();
    int selected = getSelected();
    AvatarListModel *model = static_cast<AvatarListModel*>(mListModel);
    if (!model)
        return;

    if (event.getButton() == gcn::MouseEvent::LEFT)
    {
        Avatar *ava = model->getAvatarAt(selected);
        if (!ava)
            return;

        logger->log("navigate button");

        if (ava->getLevel() >= 0)
        {
            logger->log("navigate level");
            Being* being = beingManager->findBeingByName(ava->getName(),
                        Being::PLAYER);
            if (being)
                beingManager->heal(player_node, being);
        }
        else
        {
            logger->log("navigate avatar");
            player_node->navigateTo(ava->getX(), ava->getY());
        }
    }
    else if (event.getButton() == gcn::MouseEvent::RIGHT)
    {
        Being* being = beingManager->findBeingByName(model->getAvatarAt(selected)
                                                     ->getName(), Being::PLAYER);
        if (being)
            viewport->showPopup(event.getX(), event.getY(), being);
    }
    else if (event.getButton() == gcn::MouseEvent::MIDDLE)
    {
        chatWindow->addWhisperTab(model->getAvatarAt(selected)
                                  ->getName(), true);
    }
}
