##########################################################################
#
#  Copyright (c) 2008-2010, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#     * Neither the name of Image Engine Design nor the names of any
#       other contributors to this software may be used to endorse or
#       promote products derived from this software without specific prior
#       written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import nuke
import imath
import IECore

__getters = {}
__setters = {}

##########################################################################
# public functions
##########################################################################

def registerAccessors( knobType, get, set = None ) :

	assert( not knobType in __getters )
	__getters[knobType] = get

	if set :
		assert( not knobType in __setters )
		__setters[knobType] = set

## \todo Support more knob types
def getKnobValue( knob, **kwArgs ) :

	f = __getters.get( knob.__class__, None )
	if not f :
		raise RuntimeError( "No get accessor registered for type %s", str( knob.__class__ ) )

	return f( knob, **kwArgs )

def setKnobValue( knob, value, **kwArgs ) :

	f = __setters.get( knob.__class__, None )
	if not f :
		raise RuntimeError( "No set accessor registered for type %s", str( knob.__class__ ) )

	return f( knob, value, **kwArgs )

##########################################################################
# accessor implementations
##########################################################################

# XY Knob

def __getXY( knob, resultType=imath.V2f ) :

	return resultType( knob.getValue( 0 ), knob.getValue( 1 ) )

def __setXY( knob, value ) :

	knob.setValue( value[0], 0 )
	knob.setValue( value[1], 1 )

registerAccessors( nuke.XY_Knob, __getXY, __setXY )

# XYZ Knob

def __getXYZ( knob, resultType=imath.V3f ) :

	return resultType( knob.getValue( 0 ), knob.getValue( 1 ), knob.getValue( 2 ) )

def __setXYZ( knob, value ) :

	knob.setValue( value[0], 0 )
	knob.setValue( value[1], 1 )
	knob.setValue( value[2], 2 )

registerAccessors( nuke.XYZ_Knob, __getXYZ, __setXYZ )
registerAccessors( nuke.Scale_Knob, __getXYZ, __setXYZ )

# Color Knob

def __getColor( knob, resultType=imath.Color3f ) :

	return resultType( knob.getValue( 0 ), knob.getValue( 1 ), knob.getValue( 2 ) )

def __setColor( knob, value ) :

	knob.setValue( value[0], 0 )
	knob.setValue( value[1], 1 )
	knob.setValue( value[2], 2 )

registerAccessors( nuke.Color_Knob, __getColor, __setColor )

# String Knob

def __getString( knob, resultType=str ) :

	return resultType( knob.getText() )

def __setString( knob, value ) :

	knob.setValue( str( value ) )

registerAccessors( nuke.EvalString_Knob, __getString, __setString )

# Box3 Knob

def __getBox3( knob, resultType=imath.Box3f ) :

	vectorType = imath.V3f
	if resultType == imath.Box3d :
		vectorType = imath.V3d

	value = knob.getValue()
	return resultType( vectorType( *value[:3] ), vectorType( *value[3:] ) )

def __setBox3( knob, value ) :

	knob.setX( value.min[0] )
	knob.setY( value.min[1] )
	knob.setN( value.min[2] )

	knob.setR( value.max[0] )
	knob.setT( value.max[1] )
	knob.setF( value.max[2] )

registerAccessors( nuke.Box3_Knob, __getBox3, __setBox3 )

