#=============================================================================
#
#  Copyright (c) Kitware, Inc.
#  All rights reserved.
#  See LICENSE.txt for details.
#
#  This software is distributed WITHOUT ANY WARRANTY; without even
#  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#  PURPOSE.  See the above copyright notice for more information.
#
#=============================================================================
import bisect
import math
import random
import string
import sys

import smtk

# so devs don't complain about pyc files in source
sys.dont_write_bytecode = True

def writeMethodItem(writer, i, indent):
  if i.isEnabled():
     if i.name() == "id_method":
        writer.write("%s%s = '%s'\n"%(indent,i.name(),i.valueAsString()))
     elif i.type() == smtk.attribute.Item.Type.VOID:
        writer.write("%s%s\n"%(indent,i.name()))
     else:
        writer.write("%s%s = %s\n"%(indent,i.name(),i.valueAsString()))

def writeMethod(writer, method):
  writer.write("method\n")
  print dir(method)
  gvars = ["id_method", "max_iterations", "max_function_evaluations" ]
  lvars = list()
  for count in range(0,method.numberOfItems()):
    i = method.item(count)
    if i.name() in gvars:
      tmp = smtk.attribute.to_concrete(i)
      writeMethodItem(writer, tmp, "   ")
    else:
      lvars.append(smtk.attribute.to_concrete(i))
  writer.write("   "+method.type()+"\n")
  for i in lvars:
    writeMethodItem(writer, i, "      ")

def writeVariables(writer, vars):
  cont_var = []
  print len(vars)
  for v in vars:
    print(v.name())
    if "continuous_variable" in v.type():
      cont_var.append(v)
  count = len(cont_var)
  var_init = []
  var_min = []
  var_max = []
  var_id = []
  print count
  for c in cont_var:
    print c
    for j in range(0,c.numberOfItems()):
       i = smtk.attribute.to_concrete(c.item(j))
       if i.name() == "name":
         var_id.append(i.valueAsString())
       if i.name() == "init" and i.isEnabled():
         var_init.append(i.valueAsString())
       if i.name() == "min" and i.isEnabled():
         var_min.append(i.valueAsString())
       if i.name() == "max" and i.isEnabled():
         var_max.append(i.valueAsString())
    #print "find name"
    #name = smtk.attribute.to_concrete(c.find("name"))
    #var_id.append(name.valueAsString())
    #init = smtk.attribute.to_concrete(c.find("init"))
    #if init.isEnabled():
    #  var_init.append(init.valueAsString())
    #init = None
    #minv = smtk.attribute.to_concrete(c.find("min"))
    #if minv.isEnabled():
    #  var_min.append(minv.valueAsString())
    #minv = None
    #maxv = smtk.attribute.to_concrete(c.find("max"))
    #if maxv.isEnabled():
    #  var_max.append(maxv.valueAsString())
  print var_init
  print var_min
  print var_max
  if (len(var_id) != 0 and len(var_id) != count) or (len(var_min) != 0 and len(var_min) != count) or (len(var_max) != 0 and len(var_max) != count):
    print "ERROR: could not create the variable matrix for continious_design"
  else:
    writer.write("variables\n")
    writer.write("   continuous_design = %d\n"%(count))
    writer.write("      descriptor '%s'\n"%("' '".join(var_id)))
    if len(var_init) != 0:
      writer.write("      initial_point %s\n"%(" ".join(var_init)))
    if len(var_min) != 0:
      writer.write("      lower_bounds %s\n"%(" ".join(var_min)))
    if len(var_max) != 0:
      writer.write("      upper_bounds %s\n"%(" ".join(var_max)))

def writeInterface(writer, interfaces):
  for i in interfaces:
    writer.write("interface\n")
    items = []
    for j in range(0,i.numberOfItems()):
      t = i.item(j)
      items.append(smtk.attribute.to_concrete(t))
    type = i.type()
    type = type[0:string.find(type,'_interface')]
    writer.write("   %s\n"%type)
    for j in items:
         writer.write("      %s = '%s'\n"%(j.name(), j.valueAsString()))

def writeResponces(writer, responces):
  for r in responces:
    writer.write("responses\n")
    num_objective_functions = smtk.attribute.to_concrete(r.find("num_objective_functions"))
    if num_objective_functions.isEnabled():
      writer.write("   num_objective_functions = %s\n"%num_objective_functions.valueAsString())
    calibration_terms = smtk.attribute.to_concrete(r.find("calibration_terms"))
    if calibration_terms.isEnabled():
      calibration_data_file = smtk.attribute.to_concrete(r.find("calibration_data_file"))
      calibration_file_form = smtk.attribute.to_concrete(r.find("form"))
      if not calibration_data_file.isEnabled():
        print "ERROR: should have a calibration file"
        return
      writer.write("   calibration_terms = %s\n"%calibration_terms.valueAsString())
      writer.write("      calibration_data_file = '%s'\n"%calibration_data_file.valueAsString())
      if calibration_file_form.isEnabled():
        writer.write("        %s\n"%calibration_file_form.valueAsString())
    gradiants = smtk.attribute.to_concrete(r.find("gradiants"))
    if gradiants.valueAsString() == "None":
      writer.write("   no_gradients\n")
    elif gradiants.valueAsString() == "Analytic":
      writer.write("   analytic_gradients\n")
    else:
      writer.write("   numerical_gradients\n")
    hessians = smtk.attribute.to_concrete(r.find("hessians"))
    print hessians.valueAsString()
    if hessians.valueAsString() == "None":
      writer.write("   no_hessians\n")
    elif hessians.valueAsString() == "Analytic":
      writer.write("   analytic_hessians\n")
    else:
      writer.write("   numerical_hessians\n")

def ExportCMB(spec):
  '''
  Entry function, called by CMB to write export file
  '''
  print "Export"
  manager = spec.getSimulationAttributes()
  export_manager = spec.getExportAttributes()

  att_list = export_manager.findAttributes('ExportSpec')
  if len(att_list) < 1:
      print 'ERROR - missing ExportSpec attribute'
      return False
  spec_att = att_list[0]

  print "Default"

  analysis_name = 'Default'  # default
  item = spec_att.find('AnalysisTypes')
  if item is not None:
    print "item", item
    types_item = smtk.attribute.to_concrete(item)
    print "types_item", types_item
    if types_item.isSet(0):
      print "in types_item.isSet(0)"
      analysis_name = types_item.value(0)
      print "analysis_name", analysis_name
    else:
      print "not in types_item.isSet(0)"

  print "output"

  output_file_name = 'output.txt'  # default
  item = spec_att.find('OutputFile')
  if item is not None:
      output_item = smtk.attribute.to_concrete(item)
      if output_item.isSet(0):
        value = output_item.value(0)
        if value != '':
          output_file_name = value

  writer = open(output_file_name, 'w')
  model = manager.refModelManager()

  #Write the strategy section
  strategy_att = manager.findAttribute('strategy')
  print strategy_att
  writer.write("strategy\n")
  hybrid_type = smtk.attribute.to_concrete(strategy_att.find("hybrid_type"))
  writer.write("  hybrid = " + hybrid_type.valueAsString() + "\n")
  method_list = smtk.attribute.to_concrete(strategy_att.find("method_list"))
  writer.write("     method_list = " + method_list.valueAsString()+ "\n")

  #write methods
  methods = manager.findAttributes("method")
  print len(methods)
  for m in methods:
    writeMethod(writer, m)

  #write variables
  variables = manager.findAttributes("variable")
  writeVariables(writer, variables)

  #write interface
  interfaces = manager.findAttributes("interface")
  writeInterface(writer, interfaces)

  #write responces
  responces = manager.findAttributes("responses")
  writeResponces(writer,responces)

  writer.close()

#
# Below are utility functions that are used by ExportCMB()
#

def generate_locations(grid_info, domain_id, count):
  print "get location"
  return (0,0,0)


def compute_triangle_area(grid_info, cell_id):
  print "get triangle area"
  return 0


def generate_point(grid_info, cell_id):
  print "generate point"
  return (0,0,0)
