/***************************************************************************
 *   Copyright (C) 2006 by Bram Biesbrouck                                 *
 *   b@beligum.org                                                         *
 *                                                                         *
 *   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 St, Fifth Floor, Boston, MA  02110-1301  USA.             *
 ***************************************************************************/

#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <qobjectlist.h>

#include <libinstrudeo/isdvideoproperties.h>
#include <libinstrudeo/isdrecording.h>
#include <libinstrudeo/isdvideocanvas.h>

#include "srkcommentbox.h"
#include "srkvideocanvas.h"

//-----CONSTRUCTORS-----
SRKVideoCanvas::SRKVideoCanvas(QWidget* parent, const char* name)
    : QGLWidget(parent, name),
      recording(NULL),
      scaleFactor(1),
      zoomFactor(AUTO_ZOOM_FACTOR),
      checkResize(true)
{
}

//-----DESTRUCTOR-----
SRKVideoCanvas::~SRKVideoCanvas()
{
    //Note: the recording is deleted in the SRKMainView class
}

//-----PUBLIC METHODS-----
SRKError::SRKErrorCode SRKVideoCanvas::loadRecording(ISDRecording* recording)
{
    this->recording = recording;
    
    //now we have the recording, re-init the OpenGL canvas
    initializeGL();
    resizeGL(width(), height());
    updateGL();

    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKVideoCanvas::closeRecording()
{
    //recording gets deleted in SRKMainView class
    recording = NULL;

    glClear(GL_COLOR_BUFFER_BIT);

    updateGL();

    RETURN_SUCCESS;
}

SRKError::SRKErrorCode SRKVideoCanvas::changeZoomFactor(int factor)
{
    zoomFactor = factor;
    resizeGL(width(), height());
    updateGL();

    //update all commentboxes
    QObjectList* children = (QObjectList*)this->children();
    QObject* child;
    //Note: children returns NULL if this object has no children
    if (children) {
	for (child = children->first();child; child=children->next()) {
	    SRKCommentbox* comment = dynamic_cast<SRKCommentbox*>(child);
	    if (comment) {
		comment->scaleChanged();
	    }
	}
    }

    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKVideoCanvas::update()
{
    updateGL();

    RETURN_SUCCESS;
}

//-----PROTECTED OVERLOADED GL METHODS-----
void SRKVideoCanvas::initializeGL()
{
    //keep this color synchronized with the color of the videoContainer in srkvideopanelbase.ui
    glClearColor(85.0/255.0, 85.0/255.0, 85.0/255.0, 1.0);

    if (recording!=NULL) {
	ISDVideoCanvas* c = recording->getVideoCanvas();
	if (c) {
	    c->initGL();
	}
    }
}
void SRKVideoCanvas::resizeGL(int w, int h)
{
    /*
     * This initial piece of code controls the layout of this widget
     * First of all, the scalefactor gets calculated and saved.
     * Then, a flag is set to prevent the recursed resize to go through this check.
     * Then, the widget gets resized to the scaled size of the image, so it is always the same
     * size as the image it contains.
     * Finally, the first resize call sets the flag back up and quits.
     */

    if (this->recording!=NULL) {
	if (checkResize){
	    //use the scale factor 
	    scaleFactor = calcScaleFactor();
	    checkResize = 0;
	    resize((int)((float)recording->getVideoProperties()->getWidth()*scaleFactor),
		   (int)((float)recording->getVideoProperties()->getHeight()*scaleFactor));
	    checkResize = 1;
	    return;
	}
    }
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, (GLdouble) w, 0.0, (GLdouble) h, -1000, 1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    if (this->recording!=NULL){
	//scale the image
	recording->getVideoCanvas()->updateScales(scaleFactor);
    }
}
void SRKVideoCanvas::paintGL()
{
    if (this->recording!=NULL) {
	ISDVideoCanvas* c = recording->getVideoCanvas();
	if (c) {
	    c->display();
	}
    }
}

//-----PROTECTED METHODS-----
float SRKVideoCanvas::calcScaleFactor()
{
    float scale = 1;
    
    if ((this->recording!=NULL)){
	if (zoomFactor==SRKVideoCanvas::AUTO_ZOOM_FACTOR) {
	    //instead of relying on the with given by the parent,
	    //the video takes a much space it can get in automode
	    GLfloat widthScale = (GLfloat)width()/(GLfloat)recording->getVideoProperties()->getWidth();
	    GLfloat heightScale = (GLfloat)height()/(GLfloat)recording->getVideoProperties()->getHeight();
	    
	    /*
	     * if the video is smaller then the requested size, use 100% zoomfactor,
	     * this way, the video doesn't get pixellized in automode when smaller then
	     * the available size
	     */
	    if (widthScale>1 || heightScale>1) {
		scale = 1;
	    }
	    else {
		//stretch to the smallest scale
		scale = widthScale<heightScale?widthScale:heightScale;
	    }
	}
	//if autozoom is disabled, just convert the percentage to the scale factor
	else
	    scale = (float)zoomFactor/100.0;
    }
    
    return scale;
}
