/*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 "Options.hpp"
#include "Engines/GameEngine.hpp"

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

void Options::run()
{
    //Init variables
        //Get view size
    Vector viewSize = Vector(m_window->getViewWidth(), m_window->getViewHeight());
    
    //Background ( + Title)
    TextureManager textureManager;
    FontManager fontManager;
    SoundBufferManager soundBufferManager;
    
    Sprite background( (*textureManager.getTexture("gfx/ui/title.png")), Box(0, 0, 1920.f / 2048, 1080.f / 2048) );
    background.setScale(viewSize.x / background.getWidth(), viewSize.y / background.getHeight());
    
    Text title("Options", *fontManager.getFont("fonts/default.ttf", 64));
    title.setColor(Color(255, 255, 255));
    
    title.setXPosition((viewSize.x - title.getWidth()) / 2);
    title.setYPosition(30);
    
    //Content
    SoundEngine soundEngine;
    soundEngine.setManager(soundBufferManager);
    soundEngine.setVolume(m_configuration->getMasterVolume() * m_configuration->getSoundVolume() / 100.f);
    
    MainTab mainTab(*fontManager.getFont("fonts/default.ttf", 15), (*m_configuration), textureManager, soundEngine, m_window->getAvailableModes(), 940, 430, Color(66, 112, 174));
    mainTab.setPosition((viewSize.x - mainTab.getWidth()) / 2, 135);
    
    KeyBindTab keyTab_p1((*m_configuration), 1, textureManager, (*fontManager.getFont("fonts/default.ttf", 26)),
    (*fontManager.getFont("fonts/default.ttf", 14)), soundEngine);
    keyTab_p1.setPosition(mainTab.getXPosition() + 18, mainTab.getYPosition() + mainTab.getHeight() - keyTab_p1.getHeight() - 10);
    
    KeyBindTab keyTab_p2((*m_configuration), 2, textureManager, (*fontManager.getFont("fonts/default.ttf", 26)),
    (*fontManager.getFont("fonts/default.ttf", 14)), soundEngine);
    keyTab_p2.setPosition(mainTab.getXPosition() + mainTab.getWidth() - keyTab_p2.getWidth() - 18, mainTab.getYPosition() + 10);
    
    std::vector< std::pair<int, std::string> > loadedJoysticks = m_gameEngine->getJoystickManager().getLoadedJoysticksData();
    for (unsigned int i = 0; i < loadedJoysticks.size(); i++)
    {
        keyTab_p1.addJoystickBinder(loadedJoysticks[i].first, loadedJoysticks[i].second);
        keyTab_p2.addJoystickBinder(loadedJoysticks[i].first, loadedJoysticks[i].second);
    }
    
        //Actions
    SkinBox button_skin(240.f, 60.f);
    button_skin.inactive = Sprite( (*textureManager.getTexture("gfx/ui/ui.png")), Box(0, 0, 240.f / 512, 60.f / 512) );
    button_skin.focused = Sprite( (*textureManager.getTexture("gfx/ui/ui.png")), Box(0, 64.f / 512, 240.f / 512, 60.f / 512) );
    
    SkinSound button_sounds(soundEngine, "sound/ui/menuFocus.ogg", "sound/ui/menuClick.ogg");
    
    //Apply
    TextButton applyButton("Apply", button_skin, button_sounds);    
    applyButton.setTextFont(*fontManager.getFont("fonts/default.ttf", 24));
    applyButton.setTextColor(Color(255, 255, 255));
    
    applyButton.setXPosition(mainTab.getXPosition() + mainTab.getWidth() - applyButton.getWidth() - 20);
    applyButton.setYPosition(mainTab.getYPosition() + mainTab.getHeight() - applyButton.getHeight() - 20);
    
    //Back
    TextButton backButton("< Back", button_skin, button_sounds);
    backButton.setTextFont(*fontManager.getFont("fonts/default.ttf", 24));
    backButton.setTextColor(Color(255, 255, 255));
    backButton.setPosition(30, 30);
    
    //Playlist handling
    pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER;
    
    PlaylistNotifier notifier;
    notifier.setNotifyTime(2000.f);
    notifier.setFonts(*fontManager.getFont("fonts/default.ttf", 20), *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
    Vector mouse;
    SDL_Event event;
    while (1)
    {
        //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);
                    return;
                break;
                
                case SDL_WINDOWEVENT:
                    if (event.window.event == SDL_WINDOWEVENT_RESIZED) //Window resized
                        m_window->resizeView();
                break;
                
                case SDL_JOYDEVICEADDED:
                    {
                        int instanceID = m_gameEngine->getJoystickManager().loadJoystick(event.jdevice.which);
                        if (instanceID != JOYSTICK_LOAD_ERROR)
                        {
                            std::string name = m_gameEngine->getJoystickManager().getName(instanceID);
                            keyTab_p1.addJoystickBinder(instanceID, name);
                            keyTab_p2.addJoystickBinder(instanceID, name);
                        }
                    }
                break;
                
                case SDL_JOYDEVICEREMOVED:
                    m_gameEngine->getJoystickManager().removeJoystick(event.jdevice.which);
                    m_configuration->updatePlayerDevices(event.jdevice.which);
                    
                    keyTab_p1.removeJoystickBinder(event.jdevice.which);
                    keyTab_p2.removeJoystickBinder(event.jdevice.which);
                break;
                
                case SDL_MOUSEBUTTONUP: //Mouse clicked
                    mouse.x = event.button.x;
                    mouse.y = event.button.y;
                    
                    if (applyButton.mouseClick(m_window->viewCoords(mouse)))
                    {
                        int windowWidth = m_configuration->getWindowWidth();
                        int windowHeight = m_configuration->getWindowHeight();
                        
                        mainTab.apply(*m_configuration);
                        
                        if (m_configuration->getWindowWidth() != windowWidth || windowHeight != m_configuration->getWindowHeight())
                        {
                            if (m_configuration->getFullscreen())
                                m_window->resizeWindow(m_configuration->getWindowWidth(), m_configuration->getWindowHeight(), true);
                            else
                                m_window->resizeWindow(1024, 576, false);
                            
                            //Reload
                            m_gameEngine->initOptions();
                            
                            PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                            pthread_mutex_destroy(&notifierMutex);
                            return;
                        }
                    }
                    else if (backButton.mouseClick(m_window->viewCoords(mouse)))
                    {
                        m_gameEngine->initMainMenu();
                        
                        PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                        pthread_mutex_destroy(&notifierMutex);
                        return;
                    }
                    
                    mainTab.mouseClick(m_window->viewCoords(mouse));
                    keyTab_p1.mouseClick(m_window->viewCoords(mouse));
                    keyTab_p2.mouseClick(m_window->viewCoords(mouse));
                    
                break;
                
                case SDL_MOUSEMOTION: //Mouse moved
                    mouse.x = event.motion.x;
                    mouse.y = event.motion.y;
                    
                    applyButton.mouseMove(m_window->viewCoords(mouse));
                    backButton.mouseMove(m_window->viewCoords(mouse));
                    
                    mainTab.mouseMove(m_window->viewCoords(mouse));
                    keyTab_p1.mouseMove(m_window->viewCoords(mouse));
                    keyTab_p2.mouseMove(m_window->viewCoords(mouse));
                break;
                
                case SDL_KEYDOWN:
                    // Escape was pressed, back to main menu.
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                    {
                        m_gameEngine->initMainMenu();
                        
                        PlaylistPlayer::playlistSetNotifier(PLAYLIST_MENU, NULL, NULL);
                        pthread_mutex_destroy(&notifierMutex);
                        return;
                    }
                
                break;
            }
            
            //Key event ?
            keyTab_p1.keyEvent(event);
            keyTab_p2.keyEvent(event);
        }
        
        //Display
            //Clear
        m_window->clear();
        
            //Draw
        background.draw();
        title.draw();
        
        mainTab.draw();
        keyTab_p1.draw();
        keyTab_p2.draw();
        
        applyButton.draw();
        backButton.draw();
        
            //Playlist notifier
        pthread_mutex_lock(&notifierMutex);
        
        notifier.update();
        notifier.draw();
        
        pthread_mutex_unlock(&notifierMutex);
        
            //Render
        m_window->flush();
    }
}
