import subprocess
import sys
from pathlib import Path
import os
from time import sleep
from threading import Thread
import threading
import re
import xml.etree.ElementTree as ET



max_threads=4
i=0
output_folder_name ="/bulk_convert_out/"
stream_index_modify = []
channels_index_modify = []
stream_index = []
channels_index = []
target_bps_per_channel=96000
audio_stringmap = ""

droppedFile = sys.argv[1]
droppedName = Path(droppedFile).name
originalfiles = sys.orig_argv[2:]

#long path shenanigans 
joined = (' '.join(originalfiles))
re.sub (' +', ' ', joined)
listed = re.split(r'(.+?mkv)', joined)
listed = list(filter(None, listed))
listed = [i.lstrip() for i in listed]

#droppedFile= ['test.mkv0out.mkv', "test.mkv1out.mkv","test.mkv2out.mkv","test.mkv3out.mkv","test.mkv4out.mkv","test.mkv5out.mkv"]
#get path of script location and remove the tail
head_tail = os.path.split(sys.argv[0])
output_path = head_tail[0]


#skip first part of sys.argv since it points to script location
#arguments = sys.argv[1:]
#arguments = droppedFile

#check if output folder exists, otherwise create it
isExist = os.path.exists(output_path+output_folder_name)
if not isExist:
    os.makedirs(output_path+output_folder_name)

org_count = len(listed)
finished_count = int()


class CustomThread(Thread):
    # constructor
    def __init__(self):

        # execute the base constructor
        Thread.__init__(self)
        # set a default value


    def run(self):

        #sleep(1)
        global i
        global finished_count
        global audio_stringmap
        file=listed.pop(0)
        os.rename(file, file+"i")
        mkvmerge_input = file+"i"
        
        mkv_args = 'mkvmerge.exe --output "{file}" "{mkvmerge_input}"'.format(file=file, output_path=output_path, output_folder_name=output_folder_name, mkvmerge_input=mkvmerge_input)
        
        mkv_run = subprocess.run(mkv_args)
        #wait = mkv_run.wait()
        print("before remove file")
        os.remove(file+"i")
        basename = os.path.basename(file)
        print(file)
        sleep(1)
        #find audio channels to encode
        ffprobe_args = '.\\ffprobe.exe -i "{file}" -show_entries format:streams -of xml'.format(file=file)
        print(ffprobe_args)
        ffprobe = subprocess.Popen(["powershell.exe", ffprobe_args], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF-8')
        ffprobe_out = ffprobe.communicate()[0]
        print("printing out", ffprobe_out)
        root = ET.fromstring(ffprobe_out)
        streams = root[1].findall("stream")
        for index in streams:
            if index.get("codec_type") == "audio":
                stream_channels = int(index.get("channels"))
            
                for tag in index.findall("tag"):
                    if tag.get("key") == "BPS":
                        BPS_Value = int(tag.get("value"))
                        if BPS_Value >= target_bps_per_channel*stream_channels*1.2:
                            stream_index_modify.append(int(index.get("index"))-1)
                            channels_index_modify.append(int(index.get("channels")))
                        else:
                            stream_index.append(int(index.get("index"))-1)
                            channels_index.append(int(index.get("channels")))
        x=0
        print("streams to transcode: ", stream_index_modify)
        print("channels to modify", channels_index_modify)
        print("streams to copy: ", stream_index)
        print("channels to copy: ", channels_index)
        for each in stream_index_modify:
    
            channel_layout = channels_index_modify[x]
            bitrate = int(channel_layout*target_bps_per_channel/1000)
            audio_stringmap += "-map 0:a:{each} -c:a:{each} libopus -ac:a:{each} {channel_layout} -b:a:{each} {bitrate}k ".format(each=each,bitrate=bitrate,channel_layout=channel_layout)
            x+=1
            #print(audio_stringmap)
        x=0
        for each in stream_index:
    
            channel_layout = channels_index[x]
            bitrate = int(channel_layout*target_bps_per_channel/1000)
            audio_stringmap += "-map 0:a:{each} -c:a:{each} copy ".format(each=each,bitrate=bitrate,channel_layout=channel_layout)
            x+=1
        print(audio_stringmap)


        args = 'ffmpeg.exe -analyzeduration 20000000 -probesize 20000000 -i "{file}" -fps_mode passthrough -map 0:t? -map 0:v:0? -c:v libx265 -preset slow -crf 15.4 -x265-params "no-sao=1:bframes=8:psy-rd=2:psy-rdoq=1.5:aq-mode=3:ref=6:deblock=-1,-1" -pix_fmt yuv420p10le {audio_stringmap} -map 0:s? -c:s copy -f matroska "{output_path}{output_folder_name}{basename}"'.format(file=file, output_path=output_path, output_folder_name=output_folder_name,  basename=basename, audio_stringmap=audio_stringmap)
        print(args)
        results = subprocess.Popen(args, creationflags=0x00004000, stdout=subprocess.PIPE)
        #streeamdata = results.communicate()[0]
        data = results.wait()


        if data == 0:
            i=i-1
            finished_count=finished_count+1

      

while listed != False:
    if i < max_threads:
        global self

        if bool(listed) != False:
            t1 = CustomThread()
            t1.start()
        if bool(listed) == False:
                while bool(threading.active_count() > 1):
                        print("Finished",finished_count,"out of", org_count," ")
                        sleep(1)
                t1.join()
                print("Completed",finished_count,"out of",org_count, "inputs Successfully")
                input("waiting")
                exit()
        
        print("incrementing i in loop")
        i=i+1

    else:
        print("Finished ",finished_count,"out of ", org_count)
        sleep(1)
        print("continuing ")
