#!<python_interpreter_path>

import csv
import json
import sys
from pathlib import Path

# Sample CSV data provided by the user.
# In a real-world scenario, you would read this from an existing file.
csv_content = """function_name,callee_BlockWithMultipleSuccecorsPerLoop,callee_PtrArgs,callee_MaxDomTreeLevel,callee_IsLinkOnceODR,callee_IsLocal,callee_Calls,callee_Blocks,callee_InitialSize,callee_MaxLoopDepth,callee_users,callee_InstructionPerBlock,callee_Loops,callee_conditionally_executed_blocks,callee_IsLinkOnce,callee_basic_block_count,callee_PtrCallee,callee_CallReturnPtr,callee_ConditionalBranch,callee_CBwithArg,callee_CallerHeight,callee_CallUsage,callee_IsRecursive,callee_NumCallsiteInLoop,callee_NumOfCallUsesInLoop,callee_EntryBlockFreq,callee_MaxCallsiteBlockFreq,callee_SuccessorPerBlock,callee_AvgVecInstr,callee_AvgNestedLoopLevel,callee_InstrPerLoop,caller_BlockWithMultipleSuccecorsPerLoop,caller_PtrArgs,caller_MaxDomTreeLevel,caller_IsLinkOnceODR,caller_IsLocal,caller_Calls,caller_Blocks,caller_InitialSize,caller_MaxLoopDepth,caller_users,caller_InstructionPerBlock,caller_Loops,caller_conditionally_executed_blocks,caller_IsLinkOnce,caller_basic_block_count,caller_PtrCallee,caller_CallReturnPtr,caller_ConditionalBranch,caller_CBwithArg,caller_CallerHeight,caller_CallUsage,caller_IsRecursive,caller_NumCallsiteInLoop,caller_NumOfCallUsesInLoop,caller_EntryBlockFreq,caller_MaxCallsiteBlockFreq,caller_SuccessorPerBlock,caller_AvgVecInstr,caller_AvgNestedLoopLevel,caller_InstrPerLoop,is_indirect,num_loops,opt_code,unsimplified_common_instructions,mandatory_only,switch_penalty,mandatory_kind,case_cluster_penalty,loop_level,jump_table_penalty,cost_estimate,indirect_call_penalty,nr_ctant_params,lowered_call_arg_setup,callsite_height,load_relative_intrinsic,block_freq,call_argument_setup,call_penalty,load_elimination,hot_callsite,sroa_losses,cold_callsite,sroa_savings,is_in_inner_loop,dead_blocks,is_must_tail,simplified_instructions,is_tail,constant_args,constant_offset_ptr_args,callsite_cost,cold_cc_penalty,last_call_to_static_bonus,is_multiple_blocks,nested_inlines,nested_inline_cost_estimate,threshold,node_count,edge_count,Classes
quick_sort,5.428571e+00,1.500000e+00,0.000000e+00,1.000000e+00,6.900000e+01,7.000000e+00,69,14,1,0,0,0,1,1,6,1,1,0,8,2,0,2,1,1,2,16,16,0,1,13,0,0,0,0,0,0,0,0,0,0,8,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,9,8,8,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,0,10,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,2,0,1,0,0,0,0,7,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,4,0,0,0,0,0,3,0,0,3,0,4,0,0,0,1,0,3,4,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,1,1,3,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
benchmark_quick_sort,5.095238e+00,1.476190e+00,0.000000e+00,1.000000e+00,2.450000e+01,4.000000e+00,104,21,14,0,0,0,2,1,8,0,8,1,11,3,1,1,0,6,0,2188,2188,0,1,20,0,0,0,0,0,0,0,0,0,0,5,2,2,0,0,3,0,0,2,0,0,0,2,0,0,0,0,0,2,10,1,7,0,0,0,2,1,2,0,0,0,4,0,0,0,0,3,0,0,0,9,2,9,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,3,0,1,1,0,1,0,8,4,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,2,0,0,2,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,2,1,3,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,8,0,0,0,0,1,0,0,1,1,4,0,6,0,1,1,0,1,2,2,2,0,0,0,0,0,0,0,0,
main,2.250000e+00,1.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,14,4,4,0,0,0,0,0,1,1,2,0,1,0,2,0,0,0,0,16,16,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"""

def to_bool(value):
    """Converts a string or float value to a boolean."""
    # Check for both "1.000000e+00" and "1"
    try:
        return float(value) > 0
    except (ValueError, TypeError):
        return False

def convert_csv_to_json(csv_file_path: str, json_file_path: str):
    """
    Reads a CSV file, converts its data into a JSON format based on a predefined
    schema, and writes the result to a new JSON file.
    
    Args:
        csv_file_path (str): The path to the input CSV file.
        json_file_path (str): The path to the output JSON file.
    """
    json_data = []

    # --- 1.  JSON  ---
    #  (int)
    callee_map = {
        'callee_Blocks': 'Blocks',
        'callee_Loops': 'Loops',
        'callee_Calls': 'Calls',
        'callee_ConditionalBranch': 'ConditionalBranch',
    }
    
    #  (int)
    caller_map = {
        'caller_Blocks': 'Blocks',
        'caller_Loops': 'Loops',
        'caller_Calls': 'Calls',
        'caller_ConditionalBranch': 'ConditionalBranch',
    }
    
    # : is_indirect (bool), num_loops (int), cost_estimate (float)
    generic_map = {
        'is_indirect': 'is_indirect',
        'num_loops': 'num_loops',
        'cost_estimate': 'cost_estimate',
    }
    # ----------------------------------------------------

    try:
        with open(csv_file_path, mode='r', newline='', encoding='utf-8') as csv_file:
            #  DictReader 
            csv_reader = csv.DictReader(csv_file)
            
            for row in csv_reader:
                # 
                entry = {
                    'name': row.get('function_name', 'unknown'),
                    'features': {
                        'callee': {},
                        'caller': {},
                        'generic': {}
                    }
                }
                
                # --- 2.  callee features () ---
                for csv_key, json_key in callee_map.items():
                    value = row.get(csv_key)
                    if value is not None:
                        # 
                        try:
                            entry['features']['callee'][json_key] = int(float(value))
                        except ValueError:
                            entry['features']['callee'][json_key] = 0 #  0

                # --- 3.  caller features () ---
                for csv_key, json_key in caller_map.items():
                    value = row.get(csv_key)
                    if value is not None:
                        # 
                        try:
                            entry['features']['caller'][json_key] = int(float(value))
                        except ValueError:
                            entry['features']['caller'][json_key] = 0

                # --- 4.  generic features () ---
                for csv_key, json_key in generic_map.items():
                    value = row.get(csv_key)
                    if value is not None:
                        try:
                            if json_key == 'is_indirect':
                                entry['features']['generic'][json_key] = to_bool(value)
                            elif json_key == 'num_loops':
                                entry['features']['generic'][json_key] = int(float(value))
                            elif json_key == 'cost_estimate':
                                entry['features']['generic'][json_key] = float(value)
                        except ValueError:
                             # 
                            if json_key == 'is_indirect':
                                entry['features']['generic'][json_key] = False
                            else:
                                entry['features']['generic'][json_key] = 0.0

                json_data.append(entry)

        with open(json_file_path, 'w', encoding='utf-8') as json_file:
            json.dump(json_data, json_file, indent=2, ensure_ascii=False)
        
        print(f"Successfully converted CSV data from '{csv_file_path}' to JSON and saved to '{json_file_path}'.")

    except FileNotFoundError:
        print(f"Error: The file '{csv_file_path}' was not found.")
    except Exception as e:
        print(f"An error occurred: {e}")

import os
import sys
import glob

#  convert_csv_to_json 

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python convert_csv_to_json.py <directory_path>")
        sys.exit(1)
    
    DIR_PATH = sys.argv[1]
    
    # CSV
    csv_files = glob.glob(os.path.join(DIR_PATH, "*.csv"))
    
    if not csv_files:
        print(f"No CSV files found in {DIR_PATH}")
        sys.exit(1)
    
    # CSV
    for csv_file_path in csv_files:
        # JSON
        base_name = os.path.splitext(os.path.basename(csv_file_path))[0]
        json_file_path = os.path.join("./jsons", f"{base_name}.json")
        
        print(f"Processing {csv_file_path} -> {json_file_path}")
        
        # CSV
        with open(csv_file_path, 'r') as f:
            csv_content = f.read()
        
        # 
        csv_content = csv_content.replace(" ", ",")
        
        # 
        if not csv_content.startswith("function_name,call"):
            header = "function_name,callee_BlockWithMultipleSuccecorsPerLoop,callee_PtrArgs,callee_MaxDomTreeLevel,callee_IsLinkOnceODR,callee_IsLocal,callee_Calls,callee_Blocks,callee_InitialSize,callee_MaxLoopDepth,callee_users,callee_InstructionPerBlock,callee_Loops,callee_conditionally_executed_blocks,callee_IsLinkOnce,callee_basic_block_count,callee_PtrCallee,callee_CallReturnPtr,callee_ConditionalBranch,callee_CBwithArg,callee_CallerHeight,callee_CallUsage,callee_IsRecursive,callee_NumCallsiteInLoop,callee_NumOfCallUsesInLoop,callee_EntryBlockFreq,callee_MaxCallsiteBlockFreq,callee_SuccessorPerBlock,callee_AvgVecInstr,callee_AvgNestedLoopLevel,callee_InstrPerLoop,caller_BlockWithMultipleSuccecorsPerLoop,caller_PtrArgs,caller_MaxDomTreeLevel,caller_IsLinkOnceODR,caller_IsLocal,caller_Calls,caller_Blocks,caller_InitialSize,caller_MaxLoopDepth,caller_users,caller_InstructionPerBlock,caller_Loops,caller_conditionally_executed_blocks,caller_IsLinkOnce,caller_basic_block_count,caller_PtrCallee,caller_CallReturnPtr,caller_ConditionalBranch,caller_CBwithArg,caller_CallerHeight,caller_CallUsage,caller_IsRecursive,caller_NumCallsiteInLoop,caller_NumOfCallUsesInLoop,caller_EntryBlockFreq,caller_MaxCallsiteBlockFreq,caller_SuccessorPerBlock,caller_AvgVecInstr,caller_AvgNestedLoopLevel,caller_InstrPerLoop,is_indirect,num_loops,opt_code,unsimplified_common_instructions,mandatory_only,switch_penalty,mandatory_kind,case_cluster_penalty,loop_level,jump_table_penalty,cost_estimate,indirect_call_penalty,nr_ctant_params,lowered_call_arg_setup,callsite_height,load_relative_intrinsic,block_freq,call_argument_setup,call_penalty,load_elimination,hot_callsite,sroa_losses,cold_callsite,sroa_savings,is_in_inner_loop,dead_blocks,is_must_tail,simplified_instructions,is_tail,constant_args,constant_offset_ptr_args,callsite_cost,cold_cc_penalty,last_call_to_static_bonus,is_multiple_blocks,nested_inlines,nested_inline_cost_estimate,threshold,node_count,edge_count,Classes\n"
            csv_content = header + csv_content
        
        # CSV
        with open(csv_file_path, 'w', newline='', encoding='utf-8') as f:
            f.write(csv_content)
        
        # JSON
        convert_csv_to_json(csv_file_path, json_file_path)
        
        print(f"Successfully converted {csv_file_path} to {json_file_path}")
    
    print("All CSV files processed successfully.")