/*
 *   ORXONOX - the hottest 3D action shooter ever to exist
 *                    > www.orxonox.net <
 *
 *
 *   License notice:
 *
 *   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 (at your option) 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, write to the Free Software
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 *   Author:
 *      Fabien Vultier
 *   Co-authors:
 *      ...
 *
 */

#include "HUDWeaponMode.h"

#include "util/Convert.h"
#include "util/StringUtils.h"
#include "core/CoreIncludes.h"
#include "core/class/Super.h"

namespace orxonox
{
    RegisterClass(HUDWeaponMode);

    HUDWeaponMode::HUDWeaponMode(Context* context) : OrxonoxOverlay(context)
    {
        RegisterObject(HUDWeaponMode);

        weaponIndex_ = 0;
        weaponModeIndex_ = 0;

        overlayElementIcon_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
        overlayElementIcon_->setPosition(0.0f,0.0f);
        overlayElementIcon_->setDimensions(1.0f,1.0f);
        this->background_->addChild(overlayElementIcon_);

        overlayElementReplenish_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
        overlayElementReplenish_->setPosition(0.0f,0.0f);
        overlayElementReplenish_->setDimensions(1.0f,1.0f);
        this->background_->addChild(overlayElementReplenish_);

        overlayElementMunition_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
        overlayElementMunition_->setPosition(0.0f,0.0f);
        overlayElementMunition_->setDimensions(1.0f,1.0f);
        this->background_->addChild(overlayElementMunition_);

        overlayElementState_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
        overlayElementState_->setPosition(0.0f,0.0f);
        overlayElementState_->setDimensions(1.0f,1.0f);
        this->background_->addChild(overlayElementState_);

        overlayElementIcon_->show();
        overlayElementReplenish_->show();
        overlayElementMunition_->show();
        overlayElementState_->show();

        // Create two text overlays
        this->textOverlayLeft_ = new OverlayText(this->getContext());
        assert(this->textOverlayLeft_.get());
        this->textOverlayLeft_->setCaption("?");
        textOverlayLeft_->setPickPoint(Vector2(0.0f,0.0f));
        textOverlayLeft_->setVisible(true);
        textOverlayLeft_->setAlignment(OverlayText::Alignment::Center);
        textOverlayLeft_->setTextSize(0.02f);
        textOverlayLeft_->setColour(ColourValue(0.21,0.70,0.21,1.0));
        textOverlayLeft_->setAspectCorrection(false);
        textOverlayLeft_->setZOrder(600);
        
        this->textOverlayRight_ = new OverlayText(this->getContext());
        assert(this->textOverlayRight_.get());
        this->textOverlayRight_->setCaption("?");
        textOverlayRight_->setPickPoint(Vector2(0.0f,0.0f));
        textOverlayRight_->setVisible(true);
        textOverlayRight_->setAlignment(OverlayText::Alignment::Center);
        textOverlayRight_->setTextSize(0.02f);
        textOverlayRight_->setColour(ColourValue(0.21,0.70,0.21,1.0));
        textOverlayRight_->setAspectCorrection(false);
        textOverlayRight_->setZOrder(600);

        materialNameState_ = "";

        overlayElementReplenish_->setMaterialName("Orxonox/WSHUD_Replenish");
    }

    HUDWeaponMode::~HUDWeaponMode()
    {
        if (this->isInitialized())
        {
            this->textOverlayLeft_->destroy();
            this->textOverlayRight_->destroy();
        }
    }

    void HUDWeaponMode::tick(float dt)
    {
        SUPER(HUDWeaponMode, tick, dt);

        if (this->owner_ && this->weaponMode_)
        {
            std::string lastMaterialNameState = materialNameState_;

            if (weaponMode_->getReloading())
            {
                materialNameState_ = "Orxonox/WSHUD_Reloading";
            }
            else
            {
                materialNameState_ = "Orxonox/WSHUD_Ready";
            }            

            Munition* munition = this->weaponMode_->getMunition();

            if (munition != nullptr)
            {
                MunitionDeployment deployment = munition->getMunitionDeployment();

                if (deployment == MunitionDeployment::Share)
                {
                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunitionInCurrentMagazine(weaponMode_)));
                    this->textOverlayRight_->setCaption(multi_cast<std::string>(munition->getNumMagazines()));
                }
                else if (deployment == MunitionDeployment::Stack)
                {
                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunition(weaponMode_)));
                    this->textOverlayRight_->setCaption("");
                }
                else if (deployment == MunitionDeployment::Separate)
                {
                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunitionInCurrentMagazine(weaponMode_)));
                    this->textOverlayRight_->setCaption(multi_cast<std::string>(munition->getNumMagazines()));
                }

                if (munition->getNumMunition(weaponMode_) == 0)
                {
                    materialNameState_ = "Orxonox/WSHUD_Empty";
                }

                if (munition->isA(Class(ReplenishingMunition)))
                {
                    ReplenishingMunition* replenishingMunition = dynamic_cast<ReplenishingMunition*>(munition);

                    if (replenishingMunition->canAddMagazines(1))
                    {
                        float progress = 1.0f - replenishingMunition->getProgress();
                        overlayElementReplenish_->setDimensions(1.0f,progress);                    
                    }
                    else
                    {
                        overlayElementReplenish_->setDimensions(1.0f,1.0f);
                    }
                }
            }

            if (materialNameState_ != lastMaterialNameState)
            {
                overlayElementState_->setMaterialName(materialNameState_);
            }
        }
    }    

    void HUDWeaponMode::positionChanged()
    {
        OrxonoxOverlay::positionChanged();

        positionHUDChilds();
    }

    void HUDWeaponMode::sizeChanged()
    {
        OrxonoxOverlay::sizeChanged();

        positionHUDChilds();
    }

    void HUDWeaponMode::changedOwner()
    {
        SUPER(HUDWeaponMode, changedOwner);

        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());

        materialNameState_ = ""; // Needed to set the material in the tick after a change of the owner.
    }

    void HUDWeaponMode::changedOverlayGroup()
    {
        SUPER(HUDWeaponMode, changedOverlayGroup);

        this->getOverlayGroup()->addElement(this->textOverlayLeft_.get());
        this->getOverlayGroup()->addElement(this->textOverlayRight_.get());
    }   

    void HUDWeaponMode::changedVisibility()
    {
        SUPER(HUDWeaponMode, changedVisibility);

        bool visible = this->isVisible();

        this->textOverlayLeft_->setVisible(visible);
        this->textOverlayRight_->setVisible(visible);
    }

    void HUDWeaponMode::changedName()
    {
        SUPER(HUDWeaponMode, changedName);

        //this->textOverlay_->setName(this->getName() + "text");
    }  

    void HUDWeaponMode::setWeaponMode(WeaponMode* weaponMode)
    {
        weaponMode_ = weaponMode;

        if (!weaponMode_)
        {
            return;
        }

        std::string materialName = weaponMode_->getHUDImageString();

        overlayElementIcon_->setMaterialName(materialName);

        Munition* munition = this->weaponMode_->getMunition();

        if (munition != nullptr)
        {
            MunitionDeployment deployment = munition->getMunitionDeployment();

            if (deployment == MunitionDeployment::Share)
            {
                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionShare");
            }
            else if (deployment == MunitionDeployment::Stack)
            {
                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionStack");
            }
            else if (deployment == MunitionDeployment::Separate)
            {
                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionSeparate");
            }
        }
    }

    void HUDWeaponMode::positionHUDChilds()
    {
        Vector2 size = Vector2(getSize().x*45.0f/150.0f, getSize().y);
        Vector2 offset1 = Vector2(getSize().x*82.5f/150.0f, 0.0f);
        Vector2 offset2 = Vector2(getSize().x*127.5f/150.0f, 0.0f);

        textOverlayLeft_->setPosition(getPosition() + offset1);
        textOverlayRight_->setPosition(getPosition() + offset2);

        textOverlayLeft_->setSize(size);
        textOverlayRight_->setSize(size);

        textOverlayLeft_->setTextSize(getSize().y);
        textOverlayRight_->setTextSize(getSize().y);
    }

    void HUDWeaponMode::updateSize()
    {
        this->setSize(weaponModeHUDActualSize_);
        updatePosition();
    }

    void HUDWeaponMode::updatePosition()
    {
        this->setPosition(Vector2(weaponModeHUDActualSize_.x*weaponIndex_,weaponModeHUDActualSize_.y*weaponModeIndex_) + this->positionOffset_);
    }      
}
