/*Copyright (C) 2010-2020 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu 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 3 of the License, or
(at your option) any later version.

Hikou no mizu 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 Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "ArenaMenu.hpp"
#include "Engines/GameEngine.hpp"

ArenaMenu::ArenaMenu(GameEngine *gameEngine) : m_currentArena(0),
m_gameEngine(gameEngine), m_window(gameEngine->getWindow()),
m_configuration(gameEngine->getConfiguration())
{
    
}

void ArenaMenu::previewChanged(unsigned int arenaIx)
{
    if (arenaIx >= m_arenas.size())
        return;
    
    m_previewWorld = PhysicsWorld();
    
    m_previewArena.loadFromXML(m_arenas[arenaIx].second, "cfg/arenas.xml", m_textureManager);
    m_previewArena.applyToPhysics(m_previewWorld);
    m_previewArena.subscribeObjects(m_previewWorld);
    
    m_previewBox = Box(0, 0, m_previewArena.getWidth(), m_previewArena.getHeight());
    
    float targetWidth = 500;
    float targetHeight = targetWidth * (m_previewArena.getHeight() / m_previewArena.getWidth());
    
    m_previewTargetBox = Box(m_window->getViewWidth() - targetWidth - 30, 180, targetWidth, targetHeight);
    m_previewBackground = Polygon::rectangle(0, 0, m_previewTargetBox.width + 20, m_previewTargetBox.height + 20,
                                                    Color(66, 112, 174), Color(0, 0, 0));
    m_previewBackground.setBorderSize(0.f);
    m_previewBackground.setPosition(m_previewTargetBox.left - 10, m_previewTargetBox.top - 10);
    
    m_currentArena = arenaIx;
}

void ArenaMenu::cleanPreview()
{
    m_previewWorld = PhysicsWorld();
    
    m_previewArena.removePlatforms();
    m_previewArena = Arena();
    
    m_previewBox = Box();
    m_previewTargetBox = Box();
    m_previewBackground = Polygon();
    
    m_currentArena = 0;
}

void ArenaMenu::run()
{
    cleanPreview();
    fetchNames("cfg/arenas.xml");
    
    //Init variables
        //Get view size
    Vector viewSize = Vector(m_window->getViewWidth(), m_window->getViewHeight());
    
        //Background + Titles
    Sprite background( (*m_textureManager.getTexture("gfx/ui/nagano.png")), Box(0, 0, 1920.f / 2048, 1080.f / 2048) );
    background.setScale(viewSize.x / background.getWidth(), viewSize.y / background.getHeight());
    
    Text title("Arena selection", *m_fontManager.getFont("fonts/intuitive.ttf", 74));
    title.setColor(Color(255, 255, 255));
    
    title.setXPosition(10);
    title.setYPosition(10);
    
    Text subtitle("Select the arena where the fight'll take place !", *m_fontManager.getFont("fonts/intuitive.ttf", 30));
    subtitle.setColor(Color(222, 222, 222));
    
    subtitle.setXPosition(viewSize.x - subtitle.getWidth() - 10);
    subtitle.setYPosition(title.getYPosition() + title.getHeight() + 20);
    
    Polygon titleBack = Polygon::rectangle(0, 0, viewSize.x,
                                            subtitle.getYPosition() + subtitle.getHeight() + 10,
                                            Color(66, 112, 174), Color(0, 0, 0));
    titleBack.setBorderSize(0.f);
    
        //Arena Chooser
    Camera defaultCamera(Box(0, 0, viewSize.x, viewSize.y));
    
    ArenaChooser chooser(*m_fontManager.getFont("fonts/intuitive.ttf", 32), m_textureManager, 200, 4, Color(66, 112, 174, 200));
    chooser.setPosition(10, 165);
    chooser.initialize(m_arenas, (*this));
    
    
    Sprite ui_default( (*m_textureManager.getTexture("gfx/ui/ui.png")), Box(10.f / 512, 128.f / 512, 1.f / 512, 1.f / 512) ),
    ui_hover( (*m_textureManager.getTexture("gfx/ui/ui.png")), Box(0, 128.f / 512, 1.f / 512, 1.f / 512) );
    
    SkinBox skin(200.f, 50.f, ui_default, ui_hover);
    
    TextButton launchFight("Select", skin);
    launchFight.setTextFont(*m_fontManager.getFont("fonts/intuitive.ttf", 32));
    launchFight.setTextColor(Color(255, 255, 255));
    launchFight.setPosition(viewSize.x - launchFight.getWidth() - 20,
                            viewSize.y - launchFight.getHeight() - 30);
                            
    
    //Playlist handling
    pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER;
    
    PlaylistNotifier notifier;
    notifier.setNotifyTime(2000.f);
    notifier.setFonts(*m_fontManager.getFont("fonts/default.ttf", 20), *m_fontManager.getFont("fonts/SourceHanSansJP-Normal.otf", 14));
    
    notifier.setPosition( viewSize.x - notifier.getWidth() - 20, viewSize.y - notifier.getHeight() - 20 );
    
    PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, &notifier, &notifierMutex);
    
    
    //Start screen loop
    Timer time;
    Vector mouse;
    
    float frameTime = 0.f;
    
    SDL_Event event;
    while (1)
    {
        //Manage time
        frameTime = time.getTime();
        time.reset();
        
        //Manage events
        while (m_window->pollEvent(event))
        {
            switch (event.type)
            {
                case SDL_QUIT: //Application closed
                    m_gameEngine->exit();
                    
                    PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                    pthread_mutex_destroy(&notifierMutex);
                    
                    cleanPreview();
                    return;
                break;
                
                case SDL_WINDOWEVENT:
                    if (event.window.event == SDL_WINDOWEVENT_RESIZED) //Window resized
                        m_window->resizeView();
                break;
                
                case SDL_JOYDEVICEADDED:
                    m_gameEngine->getJoystickManager().loadJoystick(event.jdevice.which);
                break;
                
                case SDL_JOYDEVICEREMOVED:
                    m_gameEngine->getJoystickManager().removeJoystick(event.jdevice.which);
                    m_configuration->updatePlayerDevices(event.jdevice.which);
                break;
                
                case SDL_MOUSEBUTTONUP: //Mouse clicked
                    mouse.x = event.button.x;
                    mouse.y = event.button.y;
                    
                    chooser.mouseClick(m_window->viewCoords(mouse));
                    
                    if (launchFight.mouseClick(m_window->viewCoords(mouse)) &&
                        m_previewArena.getWidth() > 0 && m_currentArena < m_arenas.size())
                    {
                        m_gameEngine->confFight_arena(m_arenas[m_currentArena].second);
                        m_gameEngine->initFight();
                        
                        PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                        pthread_mutex_destroy(&notifierMutex);
                        
                        cleanPreview();
                        return;
                    }
                    
                break;
                
                case SDL_MOUSEMOTION: //Mouse moved
                    mouse.x = event.motion.x;
                    mouse.y = event.motion.y;
                    
                    chooser.mouseMove(m_window->viewCoords(mouse));
                    launchFight.mouseMove(m_window->viewCoords(mouse));
                break;
                
                case SDL_KEYDOWN:
                    // Escape was pressed, back to characters' selection.
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                    {
                        // Back to characters menu.
                        m_gameEngine->initCharactersMenu();
                        
                        PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                        pthread_mutex_destroy(&notifierMutex);
                        return;
                    }
                
                break;
            }
        }
        
        chooser.update(frameTime);
        
        //Preview physics update
        m_previewWorld.update(frameTime);
        
        //Display
            //Clear
        m_window->clear();
        
            //Draw
        background.draw();
        m_previewBackground.draw();
        
        Camera::look(m_previewBox, m_previewTargetBox);
        m_previewArena.draw();
        
        defaultCamera.look(viewSize.x, viewSize.y);
        
        chooser.draw();
        launchFight.draw();
        
        titleBack.draw();
        title.draw();
        subtitle.draw();
        
            //Playlist notifier
        pthread_mutex_lock(&notifierMutex);
        
        notifier.update();
        notifier.draw();
        
        pthread_mutex_unlock(&notifierMutex);
        
            //Render
        m_window->flush();
    }
}

void ArenaMenu::fetchNames(const std::string &xmlRelPath)
{
    m_arenas.clear();
    
    //TinyXML initialization
    std::string xmlPath = BuildValues::data(xmlRelPath); //Locate absolute path to xml data
    
    TiXmlDocument xmlFile;
    xmlFile.LoadFile(xmlPath.c_str());
    
    TiXmlHandle hdl(&xmlFile);
    
    TiXmlElement *xmlElement = hdl.FirstChildElement().FirstChildElement().ToElement();
    while (xmlElement)
    {
        m_arenas.push_back( std::make_pair( xmlElement->Attribute("name"), xmlElement->Attribute("pathname") ) );
        xmlElement = xmlElement->NextSiblingElement();
    }
}
