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

file="test.txt"

max_threads=int(input("max threads: "))
print(type(max_threads))
i=0
output_folder_name ="/bulk_convert_out/"
temp_folder = "F:/temp/"
ffmpeg_temp = "F:/temp/encoded/"

target_bps_per_channel=96000

#audio_stringmap = ""



#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


#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)

def read_file(path=""):
    with open(file,'r+') as f: 
        path = f.readlines(1)
        all = f.readlines()
        f.seek(0)
        f.truncate()
        f.writelines(all)
        return path


class CustomThread(Thread):
    # constructor
    def __init__(self, input_file=""):

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


    def run(self):

        #sleep(1)
        global i
        audio_stringmap=""
        stream_index_modify = []
        channels_index_modify = []
        stream_index = []
        channels_index = []
        file = str(input_file[0])
        file = file.rstrip("\n")
        #os.rename(file, file+"i")
        basename = os.path.basename(file)
        mkvmerge_output = temp_folder+basename
        
        mkv_args = 'mkvmerge.exe --output "{mkvmerge_output}" "{file}"'.format(file=file,mkvmerge_output=mkvmerge_output, output_path=output_path, output_folder_name=output_folder_name)
        
        mkv_run = subprocess.Popen(mkv_args)
        mkv_run.wait()
        print("before remove file")
        #os.remove(file+"i")
        file = mkvmerge_output
        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")
        m_index=0
        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"))
                        print("printing index: ", index.get("index"))
                        print("printing BPS: ", BPS_Value)
                        #to fix: specifying a codec specifies it for _output stream_ not input:https://superuser.com/questions/1669264/how-is-this-ffmpeg-map-documentation-okay 
                        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")))
                            #m_index = int(index.get("index"))
                            #m_index -= 1
                            
                            c_index = int(index.get("channels"))
                            print(m_index)
                            bitrate = int(stream_channels*target_bps_per_channel/1000)
                            test_map = "-map 0:a:{m_index} -c:a:{m_index} libopus -ac:a:{m_index} {c_index} -b:a:{m_index} {bitrate}k ".format(m_index=m_index,c_index=c_index, bitrate=bitrate,stream_channels=stream_channels)
                            audio_stringmap += test_map
                            m_index+=1
                        else:
                            #stream_index.append(int(index.get("index"))-1)
                            #channels_index.append(int(index.get("channels")))
                            m_index = int(index.get("index"))
                            m_index -= 1
                            c_index = int(index.get("channels"))
                            bitrate = int(stream_channels*target_bps_per_channel/1000)
                            test_map = "-map 0:a:{m_index} -c:a:{m_index} copy ".format(m_index=m_index,c_index=c_index, bitrate=bitrate,stream_channels=stream_channels)
                            audio_stringmap += test_map
                            m_index+=1
        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:
        #    #to fix: specifying a codec specifies it for _output stream_ not input. 
        #    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 200M -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 "{ffmpeg_temp}{basename}"'.format(file=file, basename=basename, audio_stringmap=audio_stringmap, ffmpeg_temp=ffmpeg_temp)
        print(args)
        results = subprocess.Popen(args, creationflags=0x00004000, stdout=subprocess.PIPE)
        #streeamdata = results.communicate()[0]
        data = results.wait()
        arg_list = 'mkvmerge.exe --output "{output_path}{output_folder_name}/mvkmergedupdated/{basename}" "{ffmpeg_temp}{basename}"'.format(file=file, output_path=output_path, output_folder_name=output_folder_name, basename=basename, ffmpeg_temp=ffmpeg_temp)
        print(arg_list)
        merg_results = subprocess.Popen(arg_list)
        merg_results.wait()
        os.remove(mkvmerge_output)
        os.remove(ffmpeg_temp+basename)

        if data == 0:
            i=i-1


      
filesize = os.path.getsize(file)
while filesize != 0:
    if i < max_threads:
        global self
        filesize = os.path.getsize(file)
        if filesize != 0:
            input_file = read_file()
            print(input_file)
            t1 = CustomThread(input_file)
            t1.start()
        if filesize == 0:
                while bool(threading.active_count() > 1):
                        print("Finished","out of", )
                        sleep(1)
                        filesize = os.path.getsize(file)
                        if filesize != 0:
                            print("breaking while")
                            break
                filesize = os.path.getsize(file)
                if filesize != 0:
                    print("breaking if")
                    continue
                t1.join()
                print("Completed","out of", "inputs Successfully")
                input("waiting")
                exit()
        
        print("incrementing i in loop")
        i=i+1

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