/*******************************************************************************
**
** The source file for the Jahshaka animation module
** The Jahshaka Project
** Copyright (C) 2000-2005 The Jahshaka Project
** Released under the GNU General Public License
**
*******************************************************************************/

#include "keyer.h"
#include <glworldlists.h>
#include <glcore.h>
#include <qcolor.h>
#include <qslider.h>
#include <qlabel.h>
#include "keyercolorwidget.h"
#include "colordropper.h"
#include "gpumathlib.h"
#include <InputLCD.h>
#include <supergrangecontrol.h>
#include "qtcolortriangle.h"
#include <qlistview.h>
#include <jahpreferences.h>

void GLKeyer::start( )
{
	buildInterface(m_controls);
	buildInterfaceMenus(m_leftcontroller,m_rightcontroller);
	initializeObjects();

	// Update sliders to reflected selected fps
	setResolution( JahPrefs::getInstance().getJahResolution() );
}

void GLKeyer::initializeObjects()
{    
    jtrace->info( "Initializing GLKeyer");

    //make the current opengl context current so the textures can be set up properly
    makeCurrent();    
    
    ///////////////////////////////////////////////
    //this creates the default world layer using the linked list
    JahLayer* jah_layer = configureLayer ( "World", false, true, false, true );
    buildLayer(jah_layer, "World", LayerCategory::LAYER, ObjectCategory::BACKDROP );
    m_chroma_world_layer = getLayerList()->last()->getJahLayer();
    QCheckListItem* new_q_check_list_item = new QCheckListItem(m_layer_listview, "World");
    m_chroma_world_layer->setCheckListItem(new_q_check_list_item);
    m_chroma_world_layer->getCheckListItem()->setVisible(false);

	jah_layer = configureLayer ( "Base Layer", true, true, true, true );
	buildLayer(jah_layer, "Base Layer", LayerCategory::LAYER, ObjectCategory::MESHLAYER );  
    m_chroma_base_layer = getLayerList()->getLast()->getJahLayer();

    initializeListview(m_chroma_base_layer, true);

	jah_layer = configureLayer ( "Key Layer", true, true, true, true );
    buildLayer(jah_layer, "Key Layer", LayerCategory::LAYER, ObjectCategory::MESHLAYER );  
    m_chroma_key_layer = getLayerList()->getLast()->getJahLayer();

    initializeListview(m_chroma_key_layer, true);

	//call objectmenu to update ui and then update sliders
	changeSelection(0);
    updateSliders();

    /////////////////////////////////////////////////////
    //initialize the buffer used for effect outputimage buffering
    //configureBuffer(1); 

    //turn forceplay on here
    setForcePlay(true);

    //////////////////////////////////////////////////////
    // added for custom variables
    initializeVariables();

    //////////////////////////////////////////////////////
    //sets up the core functionality
    configureModuleEngine();

    //////////////////////////////////////////////////////
    //set the ui tool
    noTool();

	////////////////////////////////////////////
    //use source size renders
    VideoRenderSelect->setChecked(true);
	m_render_at_image_resolution = true;


	for (int x=7; x<=8; x++)
	{
        JahSlidersLabel[x]->hide();
#ifndef NEW_SLIDERS
        JahSlidersLCD[x]->hide();
#endif
        JahSliders[x]->hide();
	}

	/*
    JahSlidersLabel[7]->hide();
	JahSlidersLCD[7]->hide();
	JahSliders[7]->hide();

    JahSlidersLabel[8]->hide();
	JahSlidersLCD[8]->hide();
	JahSliders[8]->hide();
	*/

    setSliderValue(9, 100);
    m_soften_value = 0.0f;
}


void GLKeyer::initializeVariables(void)
{
    static bool initVariables = true;

    if (initVariables)
    {
        #define PI                  3.14159265358979323846
        #define VIEW_ANGLE			45.0
        #define VIEW_ANGLE_RADIANS 	((VIEW_ANGLE / 180.0) * PI)

        m_camera_distance = ((float)Y_RESOLUTION / 2.0) / tan(VIEW_ANGLE_RADIANS / 2.0);

        m_select_colors_individually = false;

    }
    initVariables = false;

    //customizations
    m_textures_initialized = false;
    m_use_textures_for_readback = false;
    m_gpu_select = false;
}

//this routine is used to configure the modules engine and core functionality
void GLKeyer::configureModuleEngine(void)    
{ 
	//////////////////////////////////////////////////////
    //configure the color correction mode
    
    EffectLayer* new_effect_layer;

	//if (!( gpusupport && nv_gpusupport) )
	if ( jahstd::glslSupport() )
	{
        m_gpu_select = true;
		QString title = "GPU Keyer";
        std::string guid = "";
        new_effect_layer = addEffectLayer(m_chroma_key_layer->getLayerListEntry(), title, EffectInfo::CHROMA_KEYER_GLSL_SEPARATE_ALPHA_TYPE, -1, guid); 

		if ( m_use_gpu_qcheckbox->isChecked() )
		{
		}
		else
		{
			m_use_gpu_qcheckbox->toggle();
		}
    }
	else
	{
        m_gpu_select = false;
		QString title = "CPU Keyer";
        std::string guid = "";
        new_effect_layer = addEffectLayer(getLayerList()->at(1), title, EffectInfo::CHROMA_KEYER_CPU_TYPE, -1, guid);

		if ( m_use_gpu_qcheckbox->isChecked() )
		{
			m_use_gpu_qcheckbox->toggle();
		}
		else
		{
		}
	}

    m_chroma_settings_layer = new_effect_layer->getJahLayer();
    setCurrentEffectLayer(m_chroma_settings_layer);
    m_chroma_settings_layer->setEffectsSlidersHaveChanged(true);
    m_sliders_have_changed = true;
    
}

void GLKeyer::objectMenu(int menu)
{

    changeSelection(menu);
}

//////////////////////////////////////////
// need to fix missing command below makeTexture
//////////////////////////////////////////
///////////////////////////////////////////
///////////////////////////////////////////

void GLKeyer::addClip(assetData clip)
{
    if (getActiveJahLayer() == m_chroma_key_layer || getActiveJahLayer() == m_chroma_settings_layer)
    {
        m_chroma_key_layer->assignAsset(clip, VideoCategory::IMAGE);
        m_chroma_key_layer->LoadLayerAsset(VideoCategory::IMAGE);
        m_chroma_key_layer->makeTexture();

        //set renderspace imagesize here...
        core->imagewidth  = m_chroma_key_layer->getImageWidth();
        core->imageheight = m_chroma_key_layer->getImageHeight();
    }
    else if (getActiveJahLayer() == m_chroma_base_layer)
    {
        m_chroma_base_layer->assignAsset(clip, VideoCategory::IMAGE);
        m_chroma_base_layer->LoadLayerAsset(VideoCategory::IMAGE);
        m_chroma_base_layer->makeTexture();
    }
    else
    {
        return;
    }

    if (clip.endframe > maxFrame)
    {
        maxFrame = clip.endframe;
        updatesliderEndframe(maxFrame);
        endFrameControl->setValue(maxFrame);
    }

    updateSliders();

    setSlidersHaveChanged(true);;
    
    //update start and end points to the start and end points of the source clip
    updatesliderStartframe (  clip.startframe);
    updatesliderEndframe(  clip.endframe);
    updateGL();
}

void GLKeyer::addBaseClip(assetData clip)
{
    m_chroma_base_layer->assignAsset(clip, VideoCategory::IMAGE);
    m_chroma_base_layer->LoadLayerAsset(VideoCategory::IMAGE);
    m_chroma_base_layer->makeTexture();

    //forceupdatefxbuffer = true;

    //initialize the buffer
    //if (useBuffering)
   //     initBuffer(&getLayerList()->at(0)->thelayer->textureData.objectImage);

    updateGL();
    updateSliders();

    setSlidersHaveChanged(true);;
    
    //update start and end points to the start and end points of the source clip
    updatesliderStartframe (  clip.startframe);
    updatesliderEndframe(  clip.endframe);

    //update the ui settings
    startFrameControl->setRange( clip.startframe, clip.endframe-1 );
    startFrameControl->setValue(clip.startframe);

    endFrameControl->setRange( clip.startframe+1, clip.endframe );
    endFrameControl->setValue(clip.endframe);
}

void 
GLKeyer::setBackgroundStatus(void)
{

	bool backStatus = backgroundSelect->isChecked();

	JahLayer* jah_layer = getLayerList()->at(0)->thelayer;

	jah_layer->layerStatus = backStatus;
}


void 
GLKeyer::layerClicked( QListViewItem* item )
{
    if (!item) 
    {
        return;
    }

    LayerListEntry* layer_list_entry = findLayerListEntry(item);

    if (!layer_list_entry)
    {
        return;
    }

	JahLayer* jah_layer = layer_list_entry->thelayer;
    setActiveJahLayer(jah_layer);
    QCheckListItem* check_list_item = (QCheckListItem*)jah_layer->getCheckListItem();
    jah_layer->layernodes->m_node->layer_enabled = check_list_item->isOn();

    if (jah_layer == m_chroma_key_layer)
    {
        showSliders(9);
        setDefaultSliderText();
    }
    else if (jah_layer == m_chroma_settings_layer)
    {
        hideSliders(9);
        showSliders(7);
        setColorLimitSliderLabels();
    }
    else if (jah_layer == m_chroma_base_layer)
    {
        showSliders(9);
        setDefaultSliderText();
    }

    if ( jah_layer && ((QCheckListItem*)item)->isOn() )
    {
        jah_layer->layerStatus = true;
    }
    else
    {
        jah_layer->layerStatus = false;
    }

    updateKeyframeDisplay();
    updateSliderValues();
    updateSliders();
    updateGL();
}

void GLKeyer::setColorBase( const QColor& color )
{
    //qDebug("setColorBase"); 
    int h, s, v; 
    color.getHsv( h, s, v );
     m_hsv_base.x = float(h) / 359.0f;
     m_hsv_base.y = float(s) / 255.0f;
     m_hsv_base.z = float(v) / 255.0f;
     setRgbaValues();
}

void 
GLKeyer::setHueBase(int value)
{
    m_hsv_base.x = float(value) / 359.0f;
    setRgbaValues();
}

void 
GLKeyer::setSaturationBase(int value)
{
    m_hsv_base.y = float(value) / 255.0f;
    setRgbaValues();
}

void 
GLKeyer::setValueBase(int value)
{
    m_hsv_base.z = float(value) / 255.0f;
    setRgbaValues();
}

void 
GLKeyer::setHueRange(int value)
{
    m_hsv_range.x = float(value);
    setRgbaValues();
}

void 
GLKeyer::setSaturationRange(int value)
{
    m_hsv_range.y = float(value);
    setRgbaValues();
}

void 
GLKeyer::setSoftenValue(int value)
{
    m_soften_value = float(value) / 255.0f;
    JahSlidersLCD[6]->setValue(value);
    updateGL();
}

void 
GLKeyer::setValueRange(int value)
{
    m_hsv_range.z = float(value);
    setRgbaValues();
}

void
GLKeyer::setRgbaValues()
{
    QColor min_color = m_keyer_color_widget->minColor();
    QColor max_color = m_keyer_color_widget->maxColor();

    setActiveJahLayer( getChromaSettingsLayer() );

    float4 hsv_low;
    float4 hsv_high;
    float4 rgb_low;
    float4 rgb_high;

    int red_low;
    int green_low;
    int blue_low;

    int red_high;
    int green_high;
    int blue_high;

    int hue_low;
    int saturation_low;
    int value_low;
    int hue_high;
    int saturation_high;
    int value_high;

    min_color.getHsv(&hue_low, &saturation_low, &value_low);
    hsv_low.x = float(hue_low) / 360.0f;
    hsv_low.y = float(saturation_low) / 255.0f;
    hsv_low.z = float(value_low) / 255.0f;

    max_color.getHsv(&hue_high, &saturation_high, &value_high);
    hsv_high.x = float(hue_high) / 360.0f;
    hsv_high.y = float(saturation_high) / 255.0f;
    hsv_high.z = float(value_high) / 255.0f;

    find_rgb_range_from_hsv(hsv_low, hsv_high, rgb_low, rgb_high);

    red_low = int(rgb_low.x * 255.0f);
    green_low = int(rgb_low.y * 255.0f);
    blue_low = int(rgb_low.z * 255.0f);

    red_high = int(rgb_high.x * 255.0f);
    green_high = int(rgb_high.y * 255.0f);
    blue_high = int(rgb_high.z * 255.0f);

    setXRotation( red_low );
    setYRotation( green_low );
    setZRotation( blue_low );

    setXTrans( red_high );
    setYTrans( green_high );
    setZTrans( blue_high );

    updateSliders();
}

void 
GLKeyer::createAlphaMask(void)
{
    if ( getKeyerColorWidget()->showAlphaCheckBox->isChecked() )
    {
        getCurrentEffectLayer()->setCreateChromaAlphaMask(true);
    }
    else
    {
        getCurrentEffectLayer()->setCreateChromaAlphaMask(false);
    }

    updateGL();
}

void
GLKeyer::setColorLimitSliderLabels()
{
    JahSlidersLabel[0]->setText("Red Low");
    JahSlidersLabel[1]->setText("Green Low");
    JahSlidersLabel[2]->setText("Blue Low");

    JahSlidersLabel[3]->setText("Red High");
    JahSlidersLabel[4]->setText("Green High");
    JahSlidersLabel[5]->setText("Blue High");
    JahSlidersLabel[6]->setText("Soften");
}

void 
GLKeyer::setSelectColorsIndividually(void)
{
    layerClicked( m_chroma_settings_layer->getCheckListItem() );
    JahLayer* active_layer = getActiveJahLayer();
    m_select_colors_individually = getKeyerColorWidget()->selectColorsIndividuallyCheckBox->isChecked();
    active_layer->setSelectColorsIndividually(m_select_colors_individually);
    
    updateGL();
}

void GLKeyer::showColorDropper()
{
    ColorDropper* dropper = new ColorDropper();
    dropper->setFixedSize( 128, 128 );
    getKeyerColorWidget()->qtColorTriangle->connect( dropper, SIGNAL( colorPicked( const QColor& ) ), 
                                                     SLOT( setColor( const QColor& ) ) );
    dropper->show();
}
