##########################################################################
#
#  Copyright (c) 2010-2012, 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.
#
##########################################################################

from __future__ import with_statement

import os
import sys
import shutil
import unittest
import IECore

class TestBasicPreset( unittest.TestCase ) :

	def testCopy( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.FloatParameter( "b", "", 1.0 ),
			]
		)

		testObj2 = IECore.Parameterised( "testParameterised2" )
		testObj2.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", False ),
				IECore.FloatParameter( "c", "", 0.0	),
			]
		)

		p = IECore.BasicPreset( testObj, testObj.parameters() )

		self.assertTrue( p.applicableTo( testObj, testObj.parameters() ) )
		self.assertFalse( p.applicableTo( testObj2, testObj2.parameters() ) )

		testObj.parameters()["a"].setTypedValue( False )
		testObj.parameters()["b"].setTypedValue( 0.0 )

		p( testObj, testObj.parameters() )

		self.assertEqual( testObj.parameters()["a"].getTypedValue(), True )
		self.assertEqual( testObj.parameters()["b"].getTypedValue(), 1.0 )

		p2 = IECore.BasicPreset( testObj, testObj.parameters(), parameters=( testObj.parameters()["a"], ) )

		self.assertTrue( p2.applicableTo( testObj, testObj.parameters() ) )
		self.assertTrue( p2.applicableTo( testObj2, testObj.parameters() ) )

		p2( testObj2, testObj2.parameters() )

		self.assertEqual( testObj2.parameters()["a"].getTypedValue(), True )
		self.assertEqual( testObj2.parameters()["c"].getTypedValue(), 0.0 )

	def testLoad( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.FloatParameter( "b", "", 1.0 ),
			]
		)

		testObj2 = IECore.Parameterised( "testParameterised1" )
		testObj2.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", False ),
				IECore.FloatParameter( "c", "", 0.0	),
			]
		)

		savePath = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "data", "basicPreset" ) )

		messageHandler = IECore.CapturingMessageHandler()
		with messageHandler :

			p = IECore.BasicPreset( os.path.join( savePath, "basicPresetLoadTest", "basicPresetLoadTest-1.cob" ) )

		self.assertEqual( len( messageHandler.messages ), 0 )

		self.assertTrue( p.applicableTo( testObj, testObj.parameters() ) )
		self.assertFalse( p.applicableTo( testObj2, testObj2.parameters() ) )

		testObj.parameters()["a"].setTypedValue( False )
		testObj.parameters()["b"].setTypedValue( 0.0 )

		p( testObj, testObj.parameters() )

		self.assertEqual( testObj.parameters()["a"].getTypedValue(), True )
		self.assertEqual( testObj.parameters()["b"].getTypedValue(), 1.0 )

	def testSave( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.FloatParameter( "b", "", 1.0 ),
			]
		)

		testObj2 = IECore.Parameterised( "testParameterised1" )
		testObj2.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", False ),
				IECore.FloatParameter( "c", "", 0.0	),
			]
		)

		savePath = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "data", "basicPreset" ) )

		preset = IECore.BasicPreset( testObj, testObj.parameters() )

		# Save for the classLoader and check its there, we test the 'loadability' later...
		preset.save( savePath, "basicPresetTest" )
		self.assertTrue( os.path.isfile( os.path.join( savePath, "basicPresetTest", "basicPresetTest-1.cob" ) ) )
		self.assertTrue( os.path.isfile( os.path.join( savePath, "basicPresetTest", "basicPresetTest-1.py" ) ) )

		# save without the classLoader and check its there
		preset.save( savePath, "basicPresetTest", classLoadable=False )
		self.assertTrue( os.path.isfile( os.path.join( savePath, "basicPresetTest.cob" ) ) )

		# reload
		p = IECore.BasicPreset( os.path.join( savePath, "basicPresetTest.cob" ) )

		self.assertTrue( p.applicableTo( testObj, testObj.parameters() ) )
		self.assertFalse( p.applicableTo( testObj2, testObj2.parameters() ) )

		testObj.parameters()["a"].setTypedValue( False )
		testObj.parameters()["b"].setTypedValue( 0.0 )

		p( testObj, testObj.parameters() )

		self.assertEqual( testObj.parameters()["a"].getTypedValue(), True )
		self.assertEqual( testObj.parameters()["b"].getTypedValue(), 1.0 )

		preset2 = IECore.BasicPreset( testObj, testObj.parameters(), parameters=( testObj.parameters()["a"], ) )
		preset2.save( savePath, "basicPresetTest2", classLoadable=False )

		#reload
		p2 = IECore.BasicPreset( os.path.join( savePath, "basicPresetTest2.cob" ) )

		self.assertTrue( p2.applicableTo( testObj, testObj.parameters() ) )
		self.assertTrue( p2.applicableTo( testObj2, testObj.parameters() ) )

		p2( testObj2, testObj2.parameters() )

		self.assertEqual( testObj2.parameters()["a"].getTypedValue(), True )
		self.assertEqual( testObj2.parameters()["c"].getTypedValue(), 0.0 )

	def testClassLoader( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.FloatParameter( "b", "", 1.0 ),
			]
		)

		savePath = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "data", "basicPreset" ) )
		preset = IECore.BasicPreset( testObj, testObj.parameters() )
		preset.save( savePath, "basicPresetTestClassLoader" )

		# make sure that no messages are emitted during loading
		messageHandler = IECore.CapturingMessageHandler()
		with messageHandler :

			loader = IECore.ClassLoader( IECore.SearchPath( savePath ) )
			p = loader.load( "basicPresetTestClassLoader" )()

		self.assertEqual( len( messageHandler.messages ), 0 )

		self.assertTrue( isinstance( p, IECore.BasicPreset ) )

		p.metadata()

	def testClasses( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.ClassParameter( "b", "", "IECORE_OP_PATHS", os.path.join( "maths", "multiply" ), 2 ),
			]
		)

		testObj2 = IECore.Parameterised( "testParameterised2" )
		testObj2.parameters().addParameters(
			[
				IECore.ClassParameter( "c", "",	"IECORE_OP_PATHS" ),
			]
		)

		classes1 = testObj.parameters()["b"].getClass( True )
		classes2 = testObj2.parameters()["c"].getClass( True )
		self.assertNotEqual( classes1[1:], classes2[1:] )

		p = IECore.BasicPreset( testObj, testObj.parameters()["b"] )

		self.assertTrue( p.applicableTo( testObj, testObj.parameters()["b"] ) )
		self.assertFalse( p.applicableTo( testObj, testObj.parameters() ) )
		self.assertTrue( p.applicableTo( testObj2, testObj2.parameters()["c"] ) )

		p( testObj2, testObj2.parameters()["c"] )

		classes1 = testObj.parameters()["b"].getClass( True )
		classes2 = testObj2.parameters()["c"].getClass( True )

		self.assertEqual( classes1[1:], classes2[1:] )

	def testClassVectors( self ) :

		testObj = IECore.Parameterised( "testParameterised1" )
		testObj.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", True ),
				IECore.ClassVectorParameter( "b", "", "IECORE_OP_PATHS" ),
			]
		)

		testObj.parameters()["b"].setClasses(
			[
				( "mult", os.path.join( "maths", "multiply" ), 2 ),
				( "coIO", "compoundObjectInOut", 1 ),
			]
		)

		testObj2 = IECore.Parameterised( "testParameterised2" )
		testObj2.parameters().addParameters(
			[
				IECore.ClassVectorParameter( "c", "", "IECORE_OP_PATHS" ),
			]
		)

		classes1 = [ c[1:] for c in testObj.parameters()["b"].getClasses( True ) ]
		classes2 = [ c[1:] for c in testObj2.parameters()["c"].getClasses( True ) ]

		self.assertNotEqual( classes1, classes2 )

		p = IECore.BasicPreset( testObj, testObj.parameters()["b"] )

		self.assertTrue( p.applicableTo( testObj, testObj.parameters()["b"] ) )
		self.assertFalse( p.applicableTo( testObj, testObj.parameters() ) )
		self.assertTrue( p.applicableTo( testObj2, testObj2.parameters()["c"] ) )

		p( testObj2, testObj2.parameters()["c"] )

		classes1 = [ c[1:] for c in testObj.parameters()["b"].getClasses( True ) ]
		classes2 = [ c[1:] for c in testObj2.parameters()["c"].getClasses( True ) ]

		self.assertEqual( classes1, classes2 )

	def testCompoundVectorParameter( self ) :

		p = IECore.Parameterised( "test" )
		p.parameters().addParameters(
			[
				IECore.BoolParameter( "a", "", False ),
				IECore.CompoundVectorParameter(
					"c",
					"",
					members = [
						IECore.StringVectorParameter( "s", "", IECore.StringVectorData() ),
						IECore.BoolVectorParameter( "b", "", IECore.BoolVectorData() ),
					]
				)
			]
		)

		p["c"]["s"].setValue( IECore.StringVectorData( [ "1", "2", "3" ] ) )
		p["c"]["b"].setValue( IECore.BoolVectorData( [ True, False, True ] ) )

		v = p.parameters().getValue().copy()

		preset = IECore.BasicPreset( p, p.parameters() )

		self.assertTrue( preset.applicableTo( p, p.parameters() ) )

		p.parameters().setValue( p.parameters().defaultValue )
		self.assertNotEqual( p.parameters().getValue(), v )

		preset( p, p.parameters() )

		self.assertEqual( p.parameters().getValue(), v )

	def tearDown( self ) :

		savePath = os.path.abspath( os.path.join( os.path.dirname( __file__ ), "data", "basicPreset" ) )
		paths = (
			os.path.join( savePath, "basicPresetTest" ),
			os.path.join( savePath, "basicPresetTest.cob" ),
			os.path.join( savePath, "basicPresetTest2.cob" ),
			os.path.join( savePath, "basicPresetTestClassLoader" ),
		)

		for p in paths :
			if os.path.isdir( p ) :
				shutil.rmtree( p )
			elif os.path.isfile( p ) :
				os.remove( p )

if __name__ == "__main__":
	unittest.main()

[(336, 'unittest.main', 'unittest.main', ([], {}), False, 'import unittest\n'), (47, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (55, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised2"""'], {}), False, 'import IECore\n'), (88, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (96, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (106, 'IECore.CapturingMessageHandler', 'IECore.CapturingMessageHandler', ([], {}), False, 'import IECore\n'), (126, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (134, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (185, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (198, 'IECore.CapturingMessageHandler', 'IECore.CapturingMessageHandler', ([], {}), False, 'import IECore\n'), (212, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (220, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised2"""'], {}), False, 'import IECore\n'), (246, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised1"""'], {}), False, 'import IECore\n'), (261, 'IECore.Parameterised', 'IECore.Parameterised', (['"""testParameterised2"""'], {}), False, 'import IECore\n'), (288, 'IECore.Parameterised', 'IECore.Parameterised', (['"""test"""'], {}), False, 'import IECore\n'), (156, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest.cob"""'], {}), False, 'import os\n'), (173, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest2.cob"""'], {}), False, 'import os\n'), (303, 'IECore.StringVectorData', 'IECore.StringVectorData', (["['1', '2', '3']"], {}), False, 'import IECore\n'), (304, 'IECore.BoolVectorData', 'IECore.BoolVectorData', (['[True, False, True]'], {}), False, 'import IECore\n'), (323, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest"""'], {}), False, 'import os\n'), (324, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest.cob"""'], {}), False, 'import os\n'), (325, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest2.cob"""'], {}), False, 'import os\n'), (326, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTestClassLoader"""'], {}), False, 'import os\n'), (330, 'os.path.isdir', 'os.path.isdir', (['p'], {}), False, 'import os\n'), (50, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (51, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""b"""', '""""""', '(1.0)'], {}), False, 'import IECore\n'), (58, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(False)'], {}), False, 'import IECore\n'), (59, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""c"""', '""""""', '(0.0)'], {}), False, 'import IECore\n'), (91, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (92, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""b"""', '""""""', '(1.0)'], {}), False, 'import IECore\n'), (99, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(False)'], {}), False, 'import IECore\n'), (100, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""c"""', '""""""', '(0.0)'], {}), False, 'import IECore\n'), (104, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (109, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetLoadTest"""', '"""basicPresetLoadTest-1.cob"""'], {}), False, 'import os\n'), (129, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (130, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""b"""', '""""""', '(1.0)'], {}), False, 'import IECore\n'), (137, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(False)'], {}), False, 'import IECore\n'), (138, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""c"""', '""""""', '(0.0)'], {}), False, 'import IECore\n'), (142, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (148, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest"""', '"""basicPresetTest-1.cob"""'], {}), False, 'import os\n'), (149, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest"""', '"""basicPresetTest-1.py"""'], {}), False, 'import os\n'), (153, 'os.path.join', 'os.path.join', (['savePath', '"""basicPresetTest.cob"""'], {}), False, 'import os\n'), (188, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (189, 'IECore.FloatParameter', 'IECore.FloatParameter', (['"""b"""', '""""""', '(1.0)'], {}), False, 'import IECore\n'), (193, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (201, 'IECore.SearchPath', 'IECore.SearchPath', (['savePath'], {}), False, 'import IECore\n'), (215, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (223, 'IECore.ClassParameter', 'IECore.ClassParameter', (['"""c"""', '""""""', '"""IECORE_OP_PATHS"""'], {}), False, 'import IECore\n'), (249, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(True)'], {}), False, 'import IECore\n'), (250, 'IECore.ClassVectorParameter', 'IECore.ClassVectorParameter', (['"""b"""', '""""""', '"""IECORE_OP_PATHS"""'], {}), False, 'import IECore\n'), (264, 'IECore.ClassVectorParameter', 'IECore.ClassVectorParameter', (['"""c"""', '""""""', '"""IECORE_OP_PATHS"""'], {}), False, 'import IECore\n'), (291, 'IECore.BoolParameter', 'IECore.BoolParameter', (['"""a"""', '""""""', '(False)'], {}), False, 'import IECore\n'), (321, 'os.path.dirname', 'os.path.dirname', (['__file__'], {}), False, 'import os\n'), (331, 'shutil.rmtree', 'shutil.rmtree', (['p'], {}), False, 'import shutil\n'), (332, 'os.path.isfile', 'os.path.isfile', (['p'], {}), False, 'import os\n'), (216, 'os.path.join', 'os.path.join', (['"""maths"""', '"""multiply"""'], {}), False, 'import os\n'), (256, 'os.path.join', 'os.path.join', (['"""maths"""', '"""multiply"""'], {}), False, 'import os\n'), (333, 'os.remove', 'os.remove', (['p'], {}), False, 'import os\n'), (296, 'IECore.StringVectorData', 'IECore.StringVectorData', ([], {}), False, 'import IECore\n'), (297, 'IECore.BoolVectorData', 'IECore.BoolVectorData', ([], {}), False, 'import IECore\n')]