/*
 *   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 "HUDWeaponSystem.h"

#include "core/CoreIncludes.h"
#include "core/XMLPort.h"
#include "weaponsystem/WeaponSystem.h"
#include "weaponsystem/WeaponPack.h"
#include "weaponsystem/Weapon.h"
#include "util/Convert.h"
#include "core/class/Super.h"

namespace orxonox
{
    RegisterClass(HUDWeaponSystem);

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

        weaponModeHUDSize_ = Vector2(0.0f,0.0f);
        weaponModeHUDActualSize_ = Vector2(0.0f,0.0f);        

        weapons_.clear();
        hudWeapons_.clear();
    }

    HUDWeaponSystem::~HUDWeaponSystem()
    {
        if (this->isInitialized())
        {
            destroyHUDChilds();
        }
    }

    void HUDWeaponSystem::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    {
        SUPER(HUDWeaponSystem, XMLPort, xmlelement, mode);

        XMLPortParam(HUDWeaponSystem, "weaponModeHUDSize", setWeaponModeHUDSize, getWeaponModeHUDSize, xmlelement, mode);
    }

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

        positionHUDChilds();
    }

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

        weaponModeHUDActualSize_ = this->getActualSize();

        positionHUDChilds();
    }

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

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

        updateWeaponList();
    }

    void HUDWeaponSystem::changedOverlayGroup()
    {
        SUPER(HUDWeaponSystem, changedOverlayGroup);
    }   

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

        bool visible = this->isVisible();

        for (HUDWeapon* hudWeapon : hudWeapons_)
        {
            hudWeapon->changedVisibility(); //inform all Child Overlays that our visibility has changed
            hudWeapon->setVisible(visible);
        }
    }

    void HUDWeaponSystem::changedName()
    {
        SUPER(HUDWeaponSystem, changedName);
    }  

    void HUDWeaponSystem::updateWeaponList()
    {
        if (owner_ == nullptr)
        {
            return;
        }

        weapons_.clear();

        destroyHUDChilds();

        if (owner_->getWeaponSystem())
        {
            const std::vector<WeaponPack*>& weaponPacks = owner_->getWeaponSystem()->getAllWeaponPacks();
            for (WeaponPack* weaponPack : weaponPacks)
            {
                const std::vector<Weapon*>& weapons = weaponPack->getAllWeapons();
                for (Weapon* weapon : weapons)
                {
                    this->weapons_.push_back(weapon);
                }
            }

            createHUDChilds();
            positionHUDChilds();
        }
    }

    void HUDWeaponSystem::createHUDChilds()
    {
        int positionIndex = 0;

        for (Weapon* weapon : weapons_)
        {
            HUDWeapon* hudWeapon = new HUDWeapon(this->getContext());
            hudWeapon->setOwner(owner_);
            hudWeapon->setOverlayGroup(this->getOverlayGroup());
            hudWeapon->setVisible(this->isVisible());
            hudWeapon->setWeapon(weapon);
            hudWeapon->setAspectCorrection(false);
            hudWeapon->setPickPoint(Vector2(0.0f,0.0f));

            hudWeapons_.push_back(hudWeapon);

            ++ positionIndex;
        }
    }      

    void HUDWeaponSystem::positionHUDChilds()
    {
        int positionIndex = 0;
        Vector2 offset = this->getPosition();

        for (HUDWeapon* hudWeapon : hudWeapons_)
        {
            hudWeapon->setPositionOffset(offset);
            hudWeapon->setWeaponIndex(positionIndex);
            hudWeapon->setWeaponModeHUDActualSize(this->weaponModeHUDActualSize_);

            ++ positionIndex;
        }
    }  

    void HUDWeaponSystem::destroyHUDChilds()
    {
        for (HUDWeapon* hudWeapon : hudWeapons_)
        {
            hudWeapon->destroy();
        } 

        hudWeapons_.clear();     
    }
}
