#==============================================================================================
# Functions to convert from csv/json/xml to Pyhton list_of_dictionaries object, 
#          and convert from Pyhton list of dictionaries object to csv/json/xml
#
#==============================================================================================
# Convert CSV to a list of dictionaries Python object  
# receives: CSV string
# returns:  A list of dictionaries obj
# PS. First line must have column headers
#     Elements with commas must be in double quotes
#==============================================================================================
def csv2obj(csvString):
    from io import StringIO                  #simulate file-like read from a string
    import csv                               #import CSV module

    delim = ','                              #the delimeter
    quote = '"'                              #string with commas must be enclosed in " (double quote)
    list_dict = []

    csvFile = StringIO(csvString)                    #simulate a file read from a string
#   reader  = csv.reader(csvFile, delimiter=',')
    list_list_tuple = csv.DictReader(csvFile, delimiter=delim, quotechar=quote, quoting=csv.QUOTE_ALL, skipinitialspace=True)

    for list_tuple in list_list_tuple:
        dict = {}
        for (col_name, col_value) in list_tuple.items():                #loop thru list of tuples
            dict[col_name] = col_value                                  #build the dictionary            
        list_dict.append(dict)                                          #append dict to list of dictionaries

#   print(list_dict)                                                    #print (debug)
    return(list_dict)

#==============================================================================================
# Convert CSV to a list of dictionaries Python object (Custom function instead of above) 
# receives: CSV string
# returns:  A list of dictionaries obj
# PS. First line must have column headers
#     Elements with commas must be in single or double quotes
#==============================================================================================
def csv2obj_custom(csvString):
    import re                                           #import regex module
 
    lines = csvString.split('\n')                       #split the CSV string on \n
    list_dict = []
    dict      = {}

    col_names = re.split('\s*,\s*', lines[0])           #split line1 and create list col_names

    for idx in range(1,len(lines)-1):                   #loop thru all the lines starting on line2
        col_string = ''
        replace = False 
        for char in lines[idx]:                         #loop for every character in the line
            if char == '"' or char == "'":              #if the char is " or '
                if replace: replace = False             #switch replace true/false
                else:       replace = True 
            if char == ',' and replace:                 #if char is , and replace=true
                char = '~'                              #change it to ~ (hide that comma for now) 
            col_string += char                          #rebuild the line
        col_values = re.split('\s*,\s*', col_string)    #split line on , and create list col_values
        i=0 
        for col_value in col_values:                    #loop thru the values
            col_value = re.sub('~', ',', col_value)     #revert all ~ back to , 
            col_value = re.sub('"', '' , col_value)     #get rid of any "              
            col_value = re.sub("'", "" , col_value)     #get rid of any '              
            col_name = col_names[i]                     #get the column name
            dict[col_name] = col_value                  #add col_name/col_value to dictionary
            i += 1
        list_dict.append(dict)                          #add the dictionary to the list
        dict = {}                                       #clear the dictionary                

#   print(list_dict)                                    #print (debug)
    return(list_dict)

#==============================================================================================
# convert JSON to a list of dictionaries Python object 
# receives: JSON string
# returns:  A list of dictionaries obj
#==============================================================================================
def json2obj(jsonString):
    import json                            #import JSON module

    list_dict = json.loads(jsonString)     #convert JSON data to Python object 

#   print(list_dict)                       #print (debug)
    return(list_dict)

#===============================================================================================
# convert XML to a list of dictionaries Python object  
# receives: XML string
# returns:  A list of dictionaries obj
#===============================================================================================
def xml2obj(xmlString):
    import re                                          #import regex module
 
    lines = xmlString.split('\n')                      #split the XML string on \n
    list_dict = []
    dict      = {}

    for line in lines:                                 #loop thru all the lines
        found = re.search('<(.+?)>(.*?)</.+?>',line)   #if line has <tag>content</tag> 
        if found:
            col_name  = found.group(1)                 #get the 1st group (..), the tag name
            col_value = found.group(2)                 #get the 2nd group (..), the content
            dict[col_name] = col_value                 #add the col_name & col_value to dictionary
        else:
            if dict:                                   #if the dictionary has elements
                list_dict.append(dict)                 #add the dictionary to the list
                dict = {}                              #clear the dictionary                
 
#   print(list_dict)                                   #print (debug)
    return(list_dict)
    
#===============================================================================================
# Convert a list of dictionaries obj to CSV format  
# receives: list of dictionaries obj 
# returns:  CSV multi-line string
#===============================================================================================
def obj2csv(list_dict):
    
    csv = ''
    col_names = list_dict[0].keys()                    #get all the keys from row 1
    csv += ', '.join(col_names) + '\n'                 #concatenate all col names (if headers are required) 

    for dict in list_dict:                             #loop thru all the dictionaries
        for (col_name,col_value) in dict.items():      #loop thru the column values
            if ',' in col_value:                       #if col_value has a comma , 
                dict[col_name] = '"'+ col_value +'"'   #enclosed in quotes
        col_values = dict.values()                     #get all the column values               
        csv += ', '.join(col_values)                   #concatenate all column values with ,
        csv += '\n'        

#   print(csv)                                         #print (debug)
    return(csv)                                        #return the CSV string
    
#===============================================================================================
# Convert a list of dictionaries obj to JSON format  
# receives: list of dictionaries obj 
# returns:  JSON multi-line string
#===============================================================================================
def obj2json(list_dict):
    import json                                  #import JSON module

    json = json.dumps(list_dict, indent=4)       #convert list of dictionaries to JSON string

#   print(json)                                  #print (debug)
    return(json)                                 #return the JSON string

#===============================================================================================
# Convert a list of dictionaries obj to XML format  
# receives: list of dictionaries 
# returns:  XML multi-line string
#===============================================================================================
def obj2xml(list_dict):
    
    xml  = ""
    xml  = "<?xml version='1.0'?>\n"
    xml += "<root> \n"

    for dict in list_dict:                         #loop thru the data rows
        xml += "    <row> \n"
        for (name,value) in dict.items():          #loop thru each colName/colValue
            xml +=  "        "                     #spacer
            xml += F"<{name}>{value}</{name}> \n"  #write <colName>colValue</colName>
        xml += "    </row> \n"

    xml += "</root> \n"
                
#   print(json)                                    #print (debug)
    return(xml)                                    #return the XML string

#===============================================================================================