import os
from os import path
from moviepy.editor import VideoFileClip
from moviepy.editor import concatenate_videoclips
import time

# Number of threads to use
num_threads = 2
# .../AppData/Roaming
APP_DATA_PATH: str = os.getenv('APPDATA')
# .../AppData/Local
APP_DATA_LOCAL: str = path.join(APP_DATA_PATH, "..", "Local")
# .../AppData/Local/Temp/rec
REC_DIR: str = path.join(APP_DATA_LOCAL, "Temp", "rec")
# ./output
OUTPUT_FOLDER: str = path.abspath("./output")

barrier_outer = "||"
barrier_inner = "="
barrier = "||" + "=" * (30 + len(OUTPUT_FOLDER)) + "||"

def pluralize(count):
    return "" if count == 1 else "s"

def center_text(text, num, surroundchar=""):
    """
    This function takes a string and a number as input, and prints the string repeated 
    the specified number of times, padded with spaces on both sides to reach the total length of 'num'.

    Args:
        text: The string to repeat.
        num: The number of times to repeat the string (target total length).
    """
    text_length = len(text)
    if surroundchar != "":
        text_length += len(surroundchar) * 2
    half_spaces = (num - text_length) // 2  # Integer division for even distribution
    left_pad = " " * half_spaces
    right_pad = " " * (num - text_length - half_spaces)  # Handle potential odd difference
    return surroundchar + left_pad + text + right_pad + surroundchar

while True:
    os.system('cls')
    start_time: int = time.time()

    os.makedirs(OUTPUT_FOLDER, exist_ok=True)

    print(barrier)
    print(center_text("Looking for videos to backup...", len(barrier),barrier_outer))
    print(center_text(f"Output folder: {OUTPUT_FOLDER}", len(barrier),barrier_outer))
    print(barrier)

    if not path.exists(REC_DIR):
        print(center_text(f"The directory {REC_DIR} does not exist.", len(barrier), barrier_outer))
        print(barrier)
        time.sleep(5)
        continue
    else:
        rec_dirs = os.listdir(REC_DIR)
        num_videos: int = len(rec_dirs)
        num_skipped = 0



        if num_videos == 0:
            print(center_text("No videos found, waiting.", len(barrier), barrier_outer))
            print(barrier)
            time.sleep(5)
            continue

        for i, rec_full_recording_folder in enumerate(rec_dirs):

            # full path to recording dir
            full_recording_dir: str = path.join(
                REC_DIR,
                rec_full_recording_folder
            )

            # full path to the final generated recording file
            recording_file_path: str = path.join(
                full_recording_dir,
                "fullRecording.webm"
            )

            # output recording file name
            out_recording_file_name: str = f"{rec_full_recording_folder}.mp4"
            # output recording full file path
            out_recording_file_path: str = path.join(
                OUTPUT_FOLDER,
                out_recording_file_name
            )
            if path.exists(path.join(out_recording_file_path)) and not os.path.getmtime(full_recording_dir) > os.path.getmtime(out_recording_file_path):
                num_videos -= 1
                num_skipped += 1
                continue
            try:
                if path.exists(recording_file_path):
                    # the full recording already exists

                    # create VideoFileClip object for webm file
                    clip: VideoFileClip = VideoFileClip(recording_file_path)
                    # write as mp4 file in output folder
                    clip.write_videofile(out_recording_file_path, threads=num_threads)
                    # close handle to file
                    clip.close()
                else:
                    # the recording was never generated (the recording was lost)
                    # collect all the sub-clips and sort based on their
                    # last modified time
                    sub_clip_paths = []
                    for sub_folder in os.listdir(full_recording_dir):
                        # for each of the sub clips

                        # full path to the sub clip directory
                        sub_clip_dir_full_path = path.join(
                            full_recording_dir,
                            sub_folder
                        )
                        if path.isdir(sub_clip_dir_full_path):
                            # if there exists this subclip dir

                            # full path to the subclip webm file
                            sub_clip_path = path.join(
                                sub_clip_dir_full_path,
                                "output.webm"
                            )
                            if path.exists(sub_clip_path):
                                # if the sub-clip webm file exists

                                # append this subclip path to the list of sub-clips along with it's modified time
                                sub_clip_paths.append(
                                    (
                                        sub_clip_path,
                                        os.path.getmtime(sub_clip_path)
                                    )
                                )

                    # sort the sub-clips based on their last modified time
                    sub_clip_paths.sort(key=lambda x: x[1])
                    # extract only the subclip paths
                    sorted_paths = [path for path, _ in sub_clip_paths]

                    # convert the sub-clips into VideoFileClip objects
                    clips: list[VideoFileClip] = [
                        VideoFileClip(sub_clip)
                        for sub_clip in sorted_paths
                    ]

                    # concatenate all the sub-clips into one clip
                    final_clip: VideoFileClip = concatenate_videoclips(clips)
                    # write this to the output director
                    final_clip.write_videofile(out_recording_file_path, threads=num_threads)
                    # close the handle to the file
                    final_clip.close()
            except:
                print(center_text(f"An error occured while exporting video, will try again later.", len(barrier), barrier_outer))
                print(barrier)
                time.sleep(5)
                continue

    print(center_text(f"Extracted {num_videos} video{pluralize(num_videos)} in {round(int(time.time()) - start_time, 3)} seconds.", len(barrier), barrier_outer))
    print(center_text(f"Skipped {num_skipped} video{pluralize(num_skipped)}", len(barrier), barrier_outer))
    print(barrier)
    time.sleep(5)