﻿#!/usr/bin/python


#
# Takes a nested structure and flattens the nesting in to a flat python dict with the nested path
# flattened in to a single string with a dotted seperated path for the name to lookup on.
# Eg:  val = { "blah" : { "foo" : { "x" : 5 } } }     =>     ["blah.foo.x"] = 5
# Function from http://stackoverflow.com/questions/1871524/convert-from-json-to-csv-using-python
#
def FlattenJson( val, allowEmptyArrays ):
  ret = {}
  for i in val.keys():
    if isinstance( val[i], list ):
      if len(val[i]):
        for j,v in enumerate(val[i]):
          ret[ i + "[" + str(j) + "]" ] = v
        ret = FlattenJson( ret, allowEmptyArrays )
      else:
        if allowEmptyArrays:
          ret[i + "[0]"] = ""
    elif isinstance( val[i], dict ):
      get = FlattenJson( val[i], allowEmptyArrays )
      for j in get.keys():
        ret[ i + "." + j ] = get[j]
    else:
      ret[i] = val[i]
  return ret

def FlattenJsonWithSimpleArray( val ):
  ret = {}
  for i in val.keys():
    if isinstance( val[i], list ):
      if len(val[i]):
        for myindex in range(len(val[i])):
          ret[ i + "[]" ] = val[i][myindex]
          ret = FlattenJsonWithSimpleArray( ret )
      else:
        ret[i + "[]"] = ""
    elif isinstance( val[i], dict ):
      get = FlattenJsonWithSimpleArray( val[i] )
      for j in get.keys():
        ret[ i + "." + j ] = get[j]
    else:
      ret[i] = val[i]
  return ret

#
# Basically the reverse of FlattenJson above
# Obj is the existing object to modify and assign to
# Path is a string of the hierachy to expand in to a python object tree to merge in to the Obj tree
# Val is the value to assign
#
def UnflattenJson( obj, path, val ):
  pathList = path.split('.')
  pathArray = pathList[0].split('[')

  if len(pathArray) == 2:
    # This is the case where it is an array, eg:  sim.resources[1].cost
    arrayName = pathArray[0]
    arrayIndex = int(pathArray[1][:-1])
    if not obj.has_key(arrayName):  # Here we assume the list is inside a dict
      obj[arrayName] = list()
    while len(obj[arrayName]) <= arrayIndex:
      # We are assuming that the list contains dicts, so arrays of values and arrays of arrays won't work
      # We need to know ahead what type it is
      obj[arrayName].append(dict())

    if len(pathList) == 1:
      obj[arrayName][arrayIndex] = val
    else:
      return UnflattenJson( obj[arrayName][arrayIndex], path.split('.', 1)[1], val )
  else:
    # Normal non-array item case
    if not isinstance(obj, dict):
      print ' Bad object type: ' + str(obj) + ' with path: ' + path
      return False
    if not obj.has_key(pathList[0]):
      obj[pathList[0]] = dict()

    if len(pathList) == 1:
      obj[pathList[0]] = val
    else:
      return UnflattenJson( obj[pathList[0]], path.split('.', 1)[1], val )
  return True


