/*Copyright (C) 2010-2012 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 "Window.hpp"

Window::Window() : m_frameRate(0)
{
    
}

Window::Window(const std::string &title, int width, int height, int bitsPerPixel, bool fullscreen) :
m_frameRate(0)
{
    init(width, height, bitsPerPixel, fullscreen);
    setTitle(title);
}

void Window::init(int width, int height, int bitsPerPixel, bool fullscreen)
{
    Uint32 flags = SDL_RESIZABLE | SDL_OPENGL;
    if (fullscreen) flags |= SDL_FULLSCREEN;
    
    m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
    
    //GL parameters
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}

void Window::initView(float viewWidth, float viewHeight)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    gluOrtho2D(0, viewWidth, viewHeight, 0);
    
    //Init viewport
    float windowRatio = static_cast<float>(m_screen->w) / m_screen->h;
    float glRatio = viewWidth / viewHeight;
    
    if (windowRatio > glRatio)
    {
        m_viewPort.width = viewWidth * (m_screen->h / viewHeight);
        m_viewPort.height = m_screen->h;
        
        m_viewPort.left = (m_screen->w - m_viewPort.width) / 2;
        m_viewPort.top = 0;
    }
    else
    {
        m_viewPort.width = m_screen->w;
        m_viewPort.height = viewHeight * (m_screen->w / viewWidth);
        
        m_viewPort.left = 0;
        m_viewPort.top = (m_screen->h - m_viewPort.height) / 2;
    }
    
    glViewport(m_viewPort.left, m_viewPort.top, m_viewPort.width, m_viewPort.height);
    
    m_viewWidth = viewWidth;
    m_viewHeight = viewHeight;
}

void Window::resize(int width, int height, bool fullscreen)
{
    init(width, height, m_screen->format->BitsPerPixel, fullscreen);
    initView(m_viewWidth, m_viewHeight);
}

void Window::clear(const Color &color)
{
    //Clear
    glClearColor(color.red, color.green, color.blue, color.alpha);
    glClear(GL_COLOR_BUFFER_BIT);
    
    //...view
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void Window::flush()
{
    if (m_time.getTime() < m_frameRate)
        Timer::sleep(m_frameRate - m_time.getTime());
    
    m_time.reset();
    
    glFlush();
    SDL_GL_SwapBuffers();
}

void Window::pollEvent(SDL_Event &event)
{
    SDL_PollEvent(&event);
}

void Window::waitEvent(SDL_Event &event)
{
    SDL_WaitEvent(&event);
}

Vector Window::viewCoords(const Vector &windowCoords) const
{
    Vector coords;
    coords.x = (windowCoords.x - m_viewPort.left) * (m_viewWidth / m_viewPort.width);
    coords.y = (windowCoords.y - m_viewPort.top) * (m_viewHeight / m_viewPort.height);
    
    return coords;
}

Vector Window::windowCoords(const Vector &viewCoords) const
{
    Vector coords;
    coords.x = viewCoords.x * (m_viewPort.width / m_viewWidth) + m_viewPort.left;
    coords.y = viewCoords.y * (m_viewPort.height / m_viewHeight) + m_viewPort.top;
    
    return coords;
}

//Get and set methods
void Window::setTitle(const std::string &title)
{
    SDL_WM_SetCaption(title.c_str(), NULL);
    m_title = title;
}

const std::string &Window::getTitle() const
{
    return m_title;
}

void Window::setFrameRate(float frameRate)
{
    if (frameRate > 0)
        m_frameRate = 1000 / frameRate;
    else
        m_frameRate = 0;
}

float Window::getFrameRate() const
{
    if (m_frameRate > 0)
        return 1000 / m_frameRate;
    
    return 0;
}

int Window::getWidth() const
{
    return m_screen->w;
}

int Window::getHeight() const
{
    return m_screen->h;
}

int Window::getBitsPerPixel() const
{
    return m_screen->format->BitsPerPixel;
}

float Window::getViewWidth() const
{
    return m_viewWidth;
}

float Window::getViewHeight() const
{
    return m_viewHeight;
}
