import csv
import array as arr
import numpy as np
import base64
import struct

def hexString2Base64(HEX_STRING):
    if isinstance(HEX_STRING, np.ndarray):
        HEX_STRING_ITEM = HEX_STRING.item()
        BYTE_ARRAY = bytearray.fromhex(HEX_STRING_ITEM)
        # BYTE_ARRAY = [bytearray.fromhex(hex_str) for hex_str in HEX_STRING]
    elif isinstance(HEX_STRING, str):
        BYTE_ARRAY = bytearray.fromhex(HEX_STRING)
    else: 
        raise TypeError('Input must be a string or numpy.ndarray')    
    BASE64_VAL = base64.b64encode(BYTE_ARRAY)
    return BASE64_VAL

def base64_to_hex(base64_str):
    decoded_bytes = base64.b64decode(base64_str)
    hex_str = decoded_bytes.hex()
    return hex_str

def hex_to_double(hex_str):
    # # Remove spaces and '0x' prefix if present
    # hex_str = hex_str.strip().replace("0x", "")
    byte_array = bytes.fromhex(hex_str)
    double_num = struct.unpack('!d', byte_array)[0]
    return double_num

def double_to_hex(d):
    # Convert double to hex and remove '0x' prefix
    # return hex(struct.unpack('<Q', struct.pack('<d', d))[0])[2:]
    hex_value = hex(struct.unpack('<Q', struct.pack('<d', d))[0])[2:]

    # Pad with leading zeros to ensure the length is 16
    return hex_value.zfill(16)

def numpy_array_to_hex(double_array):
    # Convert each double in the NumPy array to hex
    return [double_to_hex(d) for d in double_array]

def split_string(s,partlength):
    parts = [s[i:i+partlength] for i in range(0, len(s), partlength)]
    if len(s) % partlength != 0:
        print(f"Attention! The number is not divisible by {partlength}")
    return np.array(parts)

def findWordAfterWord(content, first_word, second_word):
    # content = reader object
    position_first_word = content.find(first_word)
    if position_first_word != -1:
    # starting from the position of first word, search for the position of second word
        position_second_word = content.find(second_word, position_first_word + len(first_word))    
        if position_second_word != -1:
            print(f"The word '{second_word}' was found at position {position_second_word}, starting from the position of '{first_word}'.")
        else:
            print(f"The word '{second_word}' was not found, starting from the position of '{first_word}'.")
    else:
        print(f"The word '{first_word}' was not found.")
    return(position_second_word)

def substringFromString(content,start_position,end_position):
    substring = content[start_position:end_position]
    substring = substring.replace('\n', '') # removes line breaks from string
    return(substring)

def insert_linebreaks(text, interval=64):
    # Split the text into chunks of the specified interval
    chunks = [text[i:i+interval] for i in range(0, len(text), interval)]
    # Join the chunks with a newline character
    result = '\n'.join(chunks)
    return result + '\n'  # add an additional line break at the very end of the string

def replaceContent(content,first_words,second_word,third_word,new_content):
    # replaces characters between specified words
    for i, x in enumerate(new_content):
        pos1 = findWordAfterWord(content,first_words[i],second_word)
        pos2 = findWordAfterWord(content,first_words[i],third_word)
        pos1 = pos1 + len(second_word)
        # content = content[:pos1] + str(x) + content[pos2:]
        content = content[:pos1] + new_content[i,0] + content[pos2:]
    print(f"String content has been edited")
    return content

def replaceContentNum(content,first_words,second_word,third_word,new_content):
    # replaces characters between specified words
    # inserts numeric values as string
    for i, x in enumerate(new_content):
        pos1 = findWordAfterWord(content,first_words[i],second_word)
        pos2 = findWordAfterWord(content,first_words[i],third_word)
        pos1 = pos1 + len(second_word)
        content = content[:pos1] + str(new_content[i]) + content[pos2:]
    print(f"String content has been edited")
    return content


###################################################################
##### UNGENUTZE FUNKTIONEN #####

# def float2base64(float_array):
#     byte_array = float_array.tobytes()
#     base64_encoded = base64.b64encode(byte_array)
#     base64_string = base64_encoded.decode('utf-8')
#     return base64_string

# def csvCol2Vec(dateipfad, col_name, row_count):
#     # moeglicherweise Effizienter als .append zu nutzen
#     colvec = np.zeros(row_count,dtype=np.float64)
#     with open(dateipfad, newline='') as csvfile:
#         csv_leser = csv.DictReader(csvfile)
#         for i, row in enumerate(csv_leser):
#             #colvec.append(row[col_name])
#             colvec[i] = float(row[col_name])
#     return colvec

# def leseZelle(dateipfad, row, col):
#     with open(dateipfad, newline='') as csvfile:
#         csv_leser = csv.reader(csvfile, delimiter=',', quotechar='"')
#         for aktuelle_zeile, zeile in enumerate(csv_leser):
#             if aktuelle_zeile == row:
#                 return zeile[col]

# def leseZeile(dateipfad, zeilennummer):
#     with open(dateipfad, newline='') as csvfile:
#         csv_leser = csv.reader(csvfile, delimiter=',', quotechar='"')
#         for aktuelle_zeile, zeile in enumerate(csv_leser):
#             if aktuelle_zeile == zeilennummer:
#                 return(zeile)
            
# def wortFinden(dateipfad, wort):
#     with open(dateipfad, 'r', encoding='utf-8') as datei:
#     # Dateicontent lesen
#         content = datei.read()

#     # Wort suchen
#     position = content.find(wort)

#     if position != -1:
#         print(f"The word'{wort}' wurde an Position {position} gefunden.")
#     else:
#         print(f"The word'{wort}' wurde nicht gefunden.")
    
#     return(position) 

# def wortNachWortFinden(dateipfad, first_word, second_word):
#     with open(dateipfad, 'r', encoding='utf-8') as datei:
#     # Dateicontent lesen
#         content = datei.read()

#     # Erstes Wort suchen
#     position_first_word = content.find(first_word)

#     if position_first_word != -1:
#     # Suche nach dem zweiten Wort ab der Position des ersten Wortes
#         position_second_word = content.find(second_word, position_first_word + len(first_word))    
#         if position_second_word != -1:
#             print(f"The word'{second_word}' wurde an Position {position_second_word} gefunden, nach dem Wort '{first_word}'.")
#         else:
#             print(f"The word'{second_word}' wurde nicht nach dem Wort '{first_word}' gefunden.")
#     else:
#         print(f"The word'{first_word}' wurde nicht gefunden.")
#     return(position_second_word)

# def wortinReaderFinden(content, wort):
#     # Wort suchen
#     position = content.find(wort)

#     if position != -1:
#         print(f"The word'{wort}' wurde an Position {position} gefunden.")
#     else:
#         print(f"The word'{wort}' wurde nicht gefunden.")
    
#     return(position) 


# def contentErsetzen(dateipfad,dateipfadNeu,start_position,end_position,new_content):
#     with open(dateipfad, 'r', encoding='utf-8') as datei:
#         content = datei.read()

#     # content zwischen den Positionen löschen und neuen content einfügen
#     geaenderter_content = content[:start_position] + new_content + content[end_position:]

#     # Geänderten content in neue Datei schreiben
#     with open(dateipfadNeu, 'w', encoding='utf-8') as dateiNeu:
#         dateiNeu.write(geaenderter_content)

#     print(f"Der content der Datei wurde abgeändert und in die Datei '{dateipfadNeu}' geschrieben")

# def contenteErsetzen(dateipfad,dateipfadNeu,first_words,second_word,third_word,new_content):
#     with open(dateipfad, 'r', encoding='utf-8') as datei:
#         content = datei.read()    
#     for i, x in enumerate(new_content):
#         pos1 = findWordAfterWord(content,first_words[i],second_word)
#         pos2 = findWordAfterWord(content,first_words[i],third_word)
#         pos1 = pos1 + len(second_word)
#         # content = content[:pos1] + str(x) + content[pos2:]
#         content = content[:pos1] + new_content[i,0] + content[pos2:]
#     with open(dateipfadNeu, 'w', encoding='utf-8') as dateiNeu:
#         dateiNeu.write(content)
#     print(f"Der content der Datei wurde abgeändert und in die Datei '{dateipfadNeu}' geschrieben")

# def contenteMitDoubleErsetzen(dateipfad,dateipfadNeu,first_words,second_word,third_word,new_content):
#     with open(dateipfad, 'r', encoding='utf-8') as datei:
#         content = datei.read()    
#     for i, x in enumerate(new_content):
#         pos1 = findWordAfterWord(content,first_words[i],second_word)
#         pos2 = findWordAfterWord(content,first_words[i],third_word)
#         pos1 = pos1 + len(second_word)
#         # content = content[:pos1] + str(x) + content[pos2:]
#         content = content[:pos1] + str(new_content[i]) + content[pos2:]
#     with open(dateipfadNeu, 'w', encoding='utf-8') as dateiNeu:
#         dateiNeu.write(content)
#     print(f"Der content der Datei wurde abgeändert und in die Datei '{dateipfadNeu}' geschrieben")

# def stringFromFile(dateipfad,start_position,end_position):
#     with open(dateipfad,'r') as datei:
#         content = datei.read()
#     substring = content[start_position:end_position]
#     substring = substring.replace('\n', '') # entfernt Zeichen für Zeilenumbrüche aus dem String
#     return(substring)