import os
import gzip
import shutil
import tempfile
from xml.etree import ElementTree as ET

# === PARAMETERS ===
root_folder = "D:/data/ableton/user/User Library/Presets/Instruments/Sampler/C soundfonts"
TARGET_VOLUME_DB = -12.0
TARGET_VELOCITY_TO_VOLUME = 1.0

# === UTILS ===

def is_gzipped(path):
    with open(path, "rb") as f:
        return f.read(2) == b'\x1f\x8b'

def load_xml_from_adv(path):
    if is_gzipped(path):
        with gzip.open(path, 'rb') as f:
            return ET.parse(f), True
    else:
        with open(path, 'r', encoding='utf-8') as f:
            return ET.ElementTree(ET.fromstring(f.read())), False

def save_xml_to_adv(tree, path, compress):
    with tempfile.NamedTemporaryFile(delete=False) as tmp:
        tree.write(tmp.name, encoding='utf-8', xml_declaration=True)
        if compress:
            with open(tmp.name, 'rb') as xml_f, gzip.open(path, 'wb') as gz_f:
                shutil.copyfileobj(xml_f, gz_f)
        else:
            shutil.copy(tmp.name, path)

def process_adv_file(path):
    try:
        tree, was_gzipped = load_xml_from_adv(path)
        root = tree.getroot()
        changed = False

        # 1. Modify <VolumeAndPan> > <Volume> > <Manual>
        vol_node = root.find("./MultiSampler/VolumeAndPan/Volume/Manual")
        vel_node = root.find("./MultiSampler/VolumeAndPan/VolumeVelScale/Manual")

        if vol_node is not None:
            old_val = vol_node.attrib.get("Value")
            vol_node.set("Value", str(TARGET_VOLUME_DB))
            print(f"  Volume: {old_val} → {TARGET_VOLUME_DB}")
            changed = True

        if vel_node is not None:
            old_val = vel_node.attrib.get("Value")
            vel_node.set("Value", str(TARGET_VELOCITY_TO_VOLUME))
            print(f"  Vel→Vol: {old_val} → {TARGET_VELOCITY_TO_VOLUME}")
            changed = True

        # 2. Modify <Value Name="Volume"> and <Value Name="VolumeVelScale">
        for val in root.findall(".//Value"):
            name = val.attrib.get("Name", "").lower()
            if name == "volume":
                old = val.attrib.get("Value")
                val.set("Value", str(TARGET_VOLUME_DB))
                print(f"  [Param] Volume: {old} → {TARGET_VOLUME_DB}")
                changed = True
            elif name in ("volumevelscale", "volumevelocityscale"):
                old = val.attrib.get("Value")
                val.set("Value", str(TARGET_VELOCITY_TO_VOLUME))
                print(f"  [Param] Vel→Vol: {old} → {TARGET_VELOCITY_TO_VOLUME}")
                changed = True

            # Remove ArrangerAutomation under Volume
            arr_automation_vol = root.find("./MultiSampler/VolumeAndPan/Volume/ArrangerAutomation")
            if arr_automation_vol is not None:
                parent = root.find("./MultiSampler/VolumeAndPan/Volume")
                parent.remove(arr_automation_vol)
                print("  Removed ArrangerAutomation from Volume")
                changed = True

            # Remove ArrangerAutomation under VolumeVelScale
            arr_automation_vel = root.find("./MultiSampler/VolumeAndPan/VolumeVelScale/ArrangerAutomation")
            if arr_automation_vel is not None:
                parent = root.find("./MultiSampler/VolumeAndPan/VolumeVelScale")
                parent.remove(arr_automation_vel)
                print("  Removed ArrangerAutomation from Vel→Vol")
                changed = True
                
        if changed:
            save_xml_to_adv(tree, path, was_gzipped)
            print(f"Modified : {path}\n")
        else:
            print(f"Nothing changed : {path}\n")

    except Exception as e:
        print(f"Error {path}: {e}")

# === PROCESS .ADV FILES ===

if __name__ == "__main__":
    print(f"Searching for .adv files in : {root_folder}\n")
    count = 0
    for root_dir, _, files in os.walk(root_folder):
        for file in files:
            if file.lower().endswith(".adv"):
                full_path = os.path.join(root_dir, file)
                print(f"Looking at : {full_path}")
                process_adv_file(full_path)
                count += 1

    print(f"\nDone : {count} files processed.")
