#!/usr/bin/env python2.2
########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################

import unittest
import os

from compClust.util.WrapperParameters import *

metrics = ['euclidean', 'correlation', 'correlation_centered']
initialization_methods = ['church_means', 'random_means', 'random_point', 'random_range', 'random_sample', 'file']
class some_params(WrapperParameters):
  _params = [
    IntProperty('k', 5, min=1, doc="Choose default k", priority=Priority.REQUIRED),
    IntProperty('seed', 42, doc="Choose a seed value for random number generator", priority=Priority.OPTIONAL),
    ComboProperty('distance_metric', 'euclidean', metrics, doc="Select distance metric %s" % (metrics), priority=Priority.REQUIRED),
    ComboProperty('initialization_method', 'church_means', initialization_methods, priority=Priority.REQUIRED, compatibility_name="init_method"),
    FloatProperty('initial_temp', 10.0, priority=Priority.EXPERIMENTAL),
    ListProperty('favorite_names', ['me'], types.StringType, priority=Priority.EXPERIMENTAL),
    StrProperty('description', priority=Priority.EXPERIMENTAL),
    StrProperty('filename', priority=Priority.INTERNAL),
    ]

class WrapperParametersTestCases(unittest.TestCase):
  def setUp(self):
    self.params = some_params()

  def tearDown(self):
    pass
  
  def testAssignment(self):
    params = some_params()
    # test integer type
    params.k = 43
    try:
      params.k = -1
    except ValueError, e:
      pass
    else:
      raise self.failureException
    try:
      params.k = 'hello'
    except ValueError, e:
      pass
    else:
      raise self.failureException
    # test combo property
    params.distance_metric = 'correlation'
    try:
      params.distance_metric = 'hello'
    except ValueError, e:
      pass
    else:
      raise self.failureException
      
  def testGetParameters(self):
    """Make sure that the getParametersDictionary returns the dictionary the wrappers want
    """
    parameters = self.params.getParametersDictionary()
    self.failUnless(parameters.has_key('k'))
    self.failUnless(parameters.has_key('init_method'))
    parameters['k'] = 7
    self.failUnless(self.params.k != parameters['k'])
    self.params.setParametersDictionary(parameters)
    self.failUnless(self.params.k == 7)
    self.failUnless(self.params['k'] == parameters['k'])
    self.params['filename'] = "greetings"
    self.failUnless(self.params._filename == "greetings")
    self.params.resetParameters()

    
  def testGetProperties(self):
    """Get all the parameters above a particular priority
    """
    required = self.params.getProperties(Priority.REQUIRED)
    self.failUnless(len(required) == 3)
    
    all = self.params.getProperties(Priority.ALL)
    self.failUnless(len(all) == 7)
    # make sure we have a doc string for all of our properties
    for prop in required.values():
      self.failUnless(getattr(self.params, prop.name).__doc__ is not None)

    # can we change things using the property functions returned through the getProperites option
    self.failUnless(self.params.k == 5)
    setattr(self.params, 'k', 3)
    self.failUnless(self.params.k == 3)
    
  def testGetProperty(self):
    """Can we retrieve a property by a name
    """
    self.failUnless(isinstance(self.params.getProperty('k'), IntProperty))

  def testFormatParameters(self):
    """So can we extract enough information in order to render user interfaces?
    """
    required = self.params.getProperties(Priority.REQUIRED)
    optional = self.params.getProperties(Priority.OPTIONAL)

    required_sort = required.keys()
    required_sort.sort()
    for prop in [ required[k] for k in required_sort ]:
      name = prop.name
      doc = prop.doc
      default = prop.default
      if isinstance(prop, NumberProperty):
        min = prop.min
        max = prop.max
      elif isinstance(prop, ComboProperty):
        choices = prop.choices
      
    
def suite(**kw):
  return unittest.makeSuite(WrapperParametersTestCases)
    
if __name__ == "__main__":
  unittest.main(defaultTest="suite")
