import os
import subprocess
import numpy as np
import uuid
from moviepy.editor import VideoFileClip
from scipy.io import wavfile
import random

video_extensions = ['.mp4', '.mkv', '.wmv', '.avi']
output_folder = 'Output'

def calculate_loudness(audio_data):
    # Calculate the loudness of audio
    if audio_data.ndim == 1:  # Mono
        volume = audio_data ** 2
    else:  # Stereo
        volume = np.mean(audio_data ** 2, axis=1)  # Mean of stereo channels
    return np.sqrt(volume)

def find_loudest_moments(audio_filename, num_moments, segment_duration, video_duration, starting_offset, ending_offset):
    rate, audio_data = wavfile.read(audio_filename)
    if audio_data.ndim == 2:
        audio_data = np.mean(audio_data, axis=1)
    volume = calculate_loudness(audio_data.astype('float32'))
    
    start_index = int(starting_offset * rate)
    end_index = int((video_duration - ending_offset) * rate)
    moments = []
    
    while len(moments) < num_moments:
        index = np.argmax(volume[start_index:end_index])
        moment = (start_index + index) / rate
        
        if moment - segment_duration / 2 < starting_offset or moment + segment_duration / 2 > video_duration - ending_offset:
            volume[start_index + index] = 0
            continue

        moments.append(moment)
        clear_margin = int(segment_duration * rate / 2)
        clear_start = max(start_index, start_index + index - clear_margin)
        clear_end = min(end_index, start_index + index + clear_margin)
        volume[clear_start:clear_end] = 0
    
    return sorted(moments)

def ask_peak_position():
    # Asking the user for peak position preference
    print("Choisissez le positionnement du pic sonore dans le segment vidéo :")
    print("1 - En début de vidéo (à un tiers)")
    print("2 - Au milieu de la vidéo")
    print("3 - En fin de vidéo (aux deux tiers)")
    print("4 - Aléatoire (à un tiers, au milieu, ou aux deux tiers)")
    choice = input("Entrez le numéro de votre choix : ")
    
    while choice not in ('1', '2', '3', '4'):
        print("Entrée invalide. Veuillez choisir une option valide.")
        choice = input("Entrez le numéro de votre choix : ")
    
    return int(choice)

def extract_segments(video_path, moments, segment_duration, peak_position_choice, video_duration):
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    base_name = os.path.splitext(os.path.basename(video_path))[0]

    for i, moment in enumerate(moments):
        # Various peak positioning options
        peak_offset_choices = {
            1: segment_duration / 3,
            2: segment_duration / 2,
            3: 2 * segment_duration / 3,
            4: random.choice([1/3, 1/2, 2/3]) * segment_duration,
        }
        peak_offset = peak_offset_choices.get(peak_position_choice, segment_duration / 2)
        start_time = max(moment - peak_offset, 0)
        end_time = min(start_time + segment_duration, video_duration)
        
        output_filename = f"{base_name}moment{i+1}.mp4"
        output_path = os.path.join(output_folder, output_filename)
        
        command = [
            "ffmpeg",
            "-y",
            "-ss", str(start_time),
            "-i", video_path,
            "-t", str(min(segment_duration, video_duration - start_time)),
            "-c:v", "libx264",
            "-preset", "medium",
            "-crf", "23",
            "-c:a", "aac",
            "-strict", "-2",
            "-b:a", "192k",
            output_path
        ]

        subprocess.run(command, check=True, stderr=subprocess.PIPE)
        print(f"Extracted and re-encoded {output_filename}")

def preliminary_loudness_analysis():
    video_loudness_info = {}
    for root, dirs, files in os.walk('.'):
        for file in files:
            if any(file.lower().endswith(ext) for ext in video_extensions):
                filepath = os.path.join(root, file)
                temp_audio = f"temp_audio{uuid.uuid4()}.wav"
                clip = VideoFileClip(filepath)
                clip.audio.write_audiofile(temp_audio, codec='pcm_s16le', fps=44100, nbytes=2, buffersize=2000, logger=None)
                clip.close()
                
                video_duration = clip.duration
                rate, audio_data = wavfile.read(temp_audio)
                if audio_data.ndim == 2:
                    audio_data = np.mean(audio_data, axis=1)
                volume = calculate_loudness(audio_data.astype(float))
                loudness_threshold = volume.mean() + volume.std() * 3  # Simple statistical threshold
                loud_moments = (volume > loudness_threshold).sum()
                
                video_loudness_info[filepath] = loud_moments
                os.remove(temp_audio)

    return video_loudness_info

def process_video_files(starting_offset_seconds, ending_offset_seconds, num_moments, segment_duration, peak_position_choice):
    # This function will be called after asking for user inputs and will follow the same
    # logic as the previous version of the script. Be sure to call this function in the 'main()'
    # after getting user inputs.
    pass

def main():
    # Perform preliminary loudness analysis and show loudness info for each video
    print("Analyzing videos for loudness…")
    video_loudness_info = preliminary_loudness_analysis()
    
    for video_path, loud_moments in video_loudness_info.items():
        print(f"'{video_path}' has {loud_moments} loud moments.")
    
    starting_offset_seconds = float(input("Combien de secondes à ignorer au début pour l'analyse ? "))
    ending_offset_seconds = float(input("Combien de secondes à ignorer à la fin pour l'analyse ? "))
    num_moments = int(input("Combien de moments forts souhaitez-vous extraire de chaque vidéo ? "))
    segment_duration = float(input("Quelle est la durée (en secondes) de chaque segment vidéo à extraire ? "))
    peak_position_choice = ask_peak_position()
    
    # Now call process_video_files with user inputs
    process_video_files(starting_offset_seconds, ending_offset_seconds, num_moments, segment_duration, peak_position_choice)
    
    print("All videos have been processed.")

if __name__ == "__main__":
    main()