#!/usr/bin/env python3



# For File managing and Interrupts
from os import system, _exit,name
import subprocess
import sys
import pathlib
from glob import glob

# For the CLI Interface
from rich import print
from tqdm import tqdm
from rich.live import Live
from rich.table import Table


VERSION = '0.2.7'

menu = f"""
 
    [bold Yellow]FFenmass[/bold Yellow]
    [bold White]CLI Utility to encode and recreate directories with ffmpeg.[/bold White]
    [bold White]Version : [/bold White][bold Red]{VERSION}[/bold Red]
                

"""







# All things directories
class DirectoryManager():

    # Check if the Directory exists, if not create it.
    def checkmake(input_path: str):
        return pathlib.Path(input_path).mkdir(parents=True, exist_ok=True)

    # Return All files from a directory tree in a sorted list.Checking against the file extension list
    def mediafiles(input_path: str):
        extension_list = ['.aif','.cda','.mid','.midi','.mp3','.mpa','.ogg','.wav','.opus','.wma','.wpl','.mka','.webm','.vob','.ogv','.ogx','.mpeg','.mpg',
                            '.3g2','.flac','.3gp','.avi','.divx','.flv','.h264','.m4v','.mkv','.mk3d','.mov','.mp4','.mpg','.mpeg','.rm','.swf','.vob','.wmv','.ts','.m2ts']
        filesonly = []
        for item in tqdm(list(glob(input_path + '/**/*', recursive=True))):
            # Excluding directories. 
            if pathlib.Path(item).is_file() and (pathlib.Path(item).suffix in extension_list):
                filesonly.append(item)
        return sorted(filesonly)


    #Generate the output path to give ffmpeg
    def outfile(file: str,input_path:str, output_path: str,extension:str):
        # Replace from file the input_path with the output_path
        fullout = file.replace(input_path,output_path)
        # Check if parent directory of file exists, if not make it.
        DirectoryManager.checkmake(pathlib.Path(fullout).parent)
        
        
        # Return the final output path with extension
        return f"{(pathlib.Path(fullout).parent).joinpath(pathlib.Path(fullout).stem)}.{extension}"



    # Check if a input_path is a directory
    def if_dir(input_path):
        if pathlib.Path(input_path).is_dir():
            return input_path
        else:
            return False


if __name__ == '__main__':
    # Cross compatible terminal clearing
    system('cls' if name == 'nt' else 'clear')

    # prints predefined menu
    print(menu)
    
    
    # Getting arguments list
    args = ['ffpb','-y']+sys.argv[1:]
    
    #Checking if input [-i] exists
    try:
        input_path = args[args.index('-i') + 1]
    except ValueError:
            print('[bold Red]ERROR : Could not catch -i argument[/bold Red]')
            try:
                sys.exit(0)
            except SystemExit:
                _exit(0)

    #Checking if input/output is valid directory, if output is not create it.
    output_path = args[len(args)-1:][0]
    if DirectoryManager.if_dir(input_path):
            pass
    else:
        print('[bold Red]Input is not a valid directory![/bold Red]')
        try:
            sys.exit(0)
        except SystemExit:
            _exit(0)
    if DirectoryManager.if_dir(output_path):
            pass
    else:
        print(f'[bold Grey]\nCreating {output_path}, because it does not exist.\n[/bold Grey]')
        DirectoryManager.checkmake(output_path)




    #Checking if extension is provided
    try:
        extension = args[args.index('-ext') + 1]

        # Checking if the argument after -ext is a directory, if yes then the user did not provide an extension
        if pathlib.Path(args[args.index('-ext') + 1]).is_file() or pathlib.Path(args[args.index('-ext') + 1]).is_dir():
            raise ValueError
        
        # Deleting the non default argument
        args.pop(args.index('-ext') + 1)
        args.pop(args.index('-ext'))
    
    except (ValueError,IndexError):
        print('[bold Red]ERROR : Could not catch -ext argument, please provide an extension.[/bold Red]')
        try:
            sys.exit(0)
        except SystemExit:
            _exit(0)
    
    
    # Removing the non standard argument to be ffmpeg compatible as its not required by ffmpeg.
    


    print(f"""
    [bold White]Input Directory :[/bold White] [bold Yellow]\"{input_path}\"[/bold Yellow]
    [bold White]Output Directory :[/bold White] [bold Yellow]\"{output_path}\"[/bold Yellow]
    [bold White]Extension :[/bold White] [bold Yellow]\"{extension}\"[/bold Yellow]""")
    print('\n')


    #Getting files
    print(f'[bold White]Grabbing files...[/bold White]\n')
    inputfiles = DirectoryManager.mediafiles(input_path=input_path)
    if inputfiles is None:
        print('[bold Red]ERROR : No Files in Directory[/bold Red]')
        try:
            sys.exit(0)
        except SystemExit:
            _exit(0)

    print(f'\n[bold White]File collection complete, {len(inputfiles)} file(s) will be processed.[/bold White]\n\n\n')
    
    
    #Main Program Loop
    for file in inputfiles:
        try:
            args[args.index('-i') + 1] = file

            args[-1] = DirectoryManager.outfile(file=file,input_path=input_path ,output_path=output_path,extension=extension)


            #Checking if file doesn't already exists on the output directory
            if not pathlib.Path(args[-1]).is_file():
                
                subprocess.run(args)

                
            # If it does, print out file exists and skip
            else:
                print(f"[bold Red]✗ Skipped[/bold Red] : [bold White]\"{pathlib.Path(args[-1]).name}\" Already Exists[/bold White]")

        # On interrupt, delete last encoded file to keep output directory free of unfinished files.
        except KeyboardInterrupt:
                print('[bold Red]Keyboard Exception, cleaning up.[/bold Red]')
                lastfile = DirectoryManager.outfile(file=file,input_path=input_path ,output_path=output_path,extension=extension)
                if pathlib.Path(lastfile).is_file():
                    pathlib.Path(lastfile).unlink(missing_ok=True)
                try:
                        
                    sys.exit(0)
                except SystemExit:
                    _exit(0)

        
            
    

    

