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

#include "coreobject.h"
#include "openmedialib.h"

// Convert ARGB to BGRA on big endian systems (will need to be modified for the systems that 
// are simply confused - intel mac being a case a point...).

static inline void convertToGLFormat( QImage& img )
{
	if ( img.depth( ) < 32 )
		img = img.convertDepth( 32 );

	if ( QImage::systemByteOrder() == QImage::BigEndian ) 
	{
		int height = img.height( );
		int width = img.width( );
		uint *p = (uint*)img.scanLine( 0 );
		uint *end = p + width;
		for ( int i = 0; i < height; i++ ) 
		{
			while ( p < end ) 
			{
				*p = ( *p << 24 ) | ( ( *p & 0xff00 ) << 8 ) | ( ( *p & 0xff0000 ) >> 8 ) | ( ( *p & 0xff000000 ) >> 24 );
				p++;
			}
			p = end;
			end += width;
		}
	}
}

//////////////////////////////////////////////////////////
//assign a asset to the layer object
//this can be audio, video, etc
void JahLayer::assignAsset(assetData clip, VideoCategory::TYPE cliptype)
{
    if (cliptype == int(VideoCategory::IMAGE))
    {
        asset = clip;

        m_inframe = clip.clipinframe;
        m_outframe = clip.clipoutframe;

        layerAssetStatus = true;
    }

    if (cliptype == VideoCategory::KEY)
    {
        jtrace->debug("ASSIGNING KEY");
        keyasset = clip;

        m_keyinframe = clip.clipinframe;
        m_keyoutframe = clip.clipoutframe;

        //this should be renamed to keyHasAsset;
        keyAssetStatus = TRUE;
    }

}

//////////////////////////////////////////////////////////////////
// initalizes a layer  as clip or key with a new media asset
// imagetype is either CLIP or KEY

bool JahLayer::LoadLayerAsset( VideoCategory::TYPE imagetype )
{
    //set up tracer
    jtrace->debug( "JahLayer::","Loading Asset into Layer");

    QImage   buf;

    //initialize the media exchange if its not already here
    //this should be moved out so its not checked every time

    if (mediaExchangePresent)
    {
		mediaExchangePresent = false;
		delete mediaExchange;
		mediaExchange = NULL;
		setEffectsSlidersHaveChanged( true ); 
	}
		
    addMediaObj();

    if (imagetype == VideoCategory::IMAGE)
    {
        buf = mediaExchange->getImage(asset, m_currentframe);
		convertToGLFormat( buf );

        updateGlTexture (buf);
        InitializeTexture(textureData);
    }

    if (imagetype == VideoCategory::NOCATEGORY)
    {
		//if its no-category we need to override
		//the image displayed
		//as we are using this for new layers
        if ( !buf.load( JahBasePath+"Pixmaps/jahlayer.png" ) ) {	// Load first image from file
            jtrace->error( "Could not read default image, using single-color instead." );
            QImage dummy( 256, 256, 32 );
            dummy.fill( Qt::blue.rgb() );
            buf = dummy;
        }

        updateGlTexture (buf);
        InitializeTexture(textureData);
    }

    if (imagetype == VideoCategory::KEY)
    {
        //this should use the keyasset
        buf = mediaExchange->getImage(keyasset, m_currentframe);
		convertToGLFormat( buf );

        if (invertKey)
        {
            buf.invertPixels();
        }

        textureKey =  buildGlTexture ( buf );
        InitializeTexture(textureKey);
    }

    return true;

}

////////////////////////////////////////////////////////////
// video and image-sequencing routines
// updates the textures in 3d space from the asset texture


void JahLayer::updateVidTex(int theframe)
{
    //////////////////////////////////////////////////////////////////
    // if there is a layer asset

    if ( layerAssetStatus )
    {
        if ( updateVidTexAsset(theframe) )
        {
            updateTexture();
        }
    }

    //////////////////////////////////////////////////////////////////
    // if there is a key asset

    if ( keyAssetStatus )
    {
        if ( updateVidTexKeyasset(theframe) )
        {
            updateKeyTexture();
        }
    }
}

bool JahLayer::updateVidTexAsset(int frame)
{
    m_currentframe = frame;
    bool flag = false;

    ////////////////////////////////////////////////////////////
    //if its a video texture it can have a slip or offset

    if ( asset.videotex )
    {
        int offset = 0;

        if      (m_inframe > 0)  { offset = m_inframe-1; }
        else if (m_inframe <= 0) { offset = m_inframe; }

        //apply the offset to curentframe
        m_currentframe -= offset;
    }

    /////////////////////////////////////////////////////////
    //the first routine checks to see if we are inside the bounds of the clip

    if ( (m_currentframe >= asset.startframe) && (m_currentframe <= asset.endframe) )
    {
        flag = true;

        mediaExchange->getStreamImagePtr(asset, textureData.objectImage, m_currentframe);
		convertToGLFormat( textureData.objectImage );
        InitializeTexture(textureData);
    }
    else
    {
        //////////////////////////////////////////////////////////
        //if we are outside the limits then we can either
        //hold start and end frame (default) or loop or ping pong

        if (loop)
        {
            //this is currently assuming that we are > endFrame
            int cf = m_currentframe;
            int cnt = 0;  //counter used for ping pong
            int nf = asset.endframe - asset.startframe + 1;  //number of frames

            if (nf > 0)
            {
                while (cf >= asset.endframe)
                {
                    cf = cf - nf;
                    cnt += 1;
                }

                if (ping && (cnt % 2 != 0) )
                {
                    cf = nf - cf;
                }
            }

            //update texturedata
            flag = true;
            mediaExchange->getStreamImagePtr(asset, textureData.objectImage, cf);
			convertToGLFormat( textureData.objectImage );
            InitializeTexture(textureData);

        }
    }

	setEffectsSlidersHaveChanged( true ); 

    return flag;
}

bool JahLayer::updateVidTexKeyasset(int frame)
{
    m_keycurrentframe = frame;
    bool flag = false;

    //is the key a videolayer or a still?
    if ( keyasset.videotex )
    {
        //this is where we compute the offset for the key
        //same as above for videolayer
        int keyoffset = 0;

        if (m_keyinframe > 0)       { keyoffset = m_keyinframe-1; }
        else if (m_keyinframe <= 0) { keyoffset = m_keyinframe; }

        //apply the offset to curentframe
        m_keycurrentframe -= keyoffset;
    }

    if ( (m_keycurrentframe >= keyasset.startframe) && (m_keycurrentframe<=keyasset.endframe) )
    {
        flag = true;

        mediaExchange->getStreamImagePtr(keyasset, textureKey.objectImage, m_keycurrentframe);
		convertToGLFormat( textureData.objectImage );

        if (invertKey) { textureKey.objectImage.invertPixels(); }
        InitializeTexture(textureKey);

    }
    else
    {
        //////////////////////////////////////////////////////////
        //if we are outside the limits then we can either
        //hold start and end frame (default) or loop or ping pong

        if (loop)
        {
            //this is currently assuming that we are > endFrame
            int cf = m_keycurrentframe;
            int cnt = 0;  //counter used for ping pong
            int nf = keyasset.endframe - keyasset.startframe + 1;  //number of frames

            if (nf>0)
            {
                while (cf>=keyasset.endframe)
                {
                    cf = cf - nf;
                    cnt += 1;
                }

            if (ping && (cnt % 2 != 0) )
                cf = nf - cf;
            }

            //update texturedata
            flag = true;

            mediaExchange->getStreamImagePtr(keyasset, textureKey.objectImage, cf);
			convertToGLFormat( textureData.objectImage );

            if (invertKey) { textureKey.objectImage.invertPixels(); }
            InitializeTexture(textureKey);
        }
    }

    return flag;
}
