import os, subprocess, json
from shlex import quote

class FileCmds:
    def __init__(self, file_path):
        super().__init__()
        self.file_path = file_path
        self.track_count = self.track_count()
        self.basic_info = self.generate_basic()
        self.advanced_info = self.generate_advanced()
        self.tabs_list = self.generate_tabs_list()
        self.tabs_content = self.generate_tabs_content()


    def execute_bash(self, cmd):
        '''
        Execute a bash command

        :type cmd: str
        :return: str   
        '''
        process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
        output, error = process.communicate()
        return output


    def file_exist(self):
        '''
        Check if the file exists

        :rtype: bool   
        '''
        if os.path.exists(self.file_path):
            return True             
        else:
            print("The file doesn't exist")
            return False


    def media_inform(self, inform):
        '''
        Execute mediainfo --Inform

        :type inform: str
        :rtype: str   
        '''
        bash_command = f"mediainfo --Inform={quote(inform)} {quote(self.file_path)}"
        output = self.execute_bash(bash_command).decode('utf-8')
        return output


    def track_count(self):
        '''
        Return the number of track of each type

        :rtype: dict[str,int]
        '''
        track_types = [
                        "Video",
                        "Audio",
                        "Text",
                        "Image",
                        "Menu",
                    ]

        output = {}

        for track_type in track_types:
            count = self.media_inform(f"General;%{track_type}Count%").replace('\n', '')
            if not count:
                count = 0
            output[track_type] = int(count)

        return output


    def generate_basic(self):
        '''
        Return the basic tab

        :rtype: string
        '''
        inform_general = r"General;G: %Format%, %FileSize_String%, %Duration_String%, %BitRate_String%\n"
        inform_video = r"Video;V: %Format%, %Format_Profile%, %StreamSize_String%, %Width%x%Height%, %FrameRate% FPS, %BitRate_String%\n"
        inform_audio = r"Audio;A: %Language_String%, %Format%, %StreamSize_String%, %BitRate_String%, %Channel(s)_String%, %SamplingRate_String%\n"
        inform_text = r"Text;T: %Language_String%, %Format%\n"

        informs = [inform_general]
        
        if not self.track_count["Video"] == 0:
            informs.append(inform_video)

        if not self.track_count["Audio"] == 0:
            informs.append(inform_audio)

        if not self.track_count["Text"] == 0:
            informs.append(inform_text)

        output = ""

        for inform in informs:
            output += self.media_inform(inform)
            
        if not self.track_count["Menu"] == 0:
            output += "M: Menu\n\n"

        output += "\n"
        output += self.execute_bash(f"mediainfo {quote(self.file_path)}").decode('utf-8')
        return(output)


    def generate_advanced(self):
        '''
        Return the advanced tab

        :rtype: string
        '''
        output = self.execute_bash(f"mediainfo --Full {quote(self.file_path)}").decode('utf-8')
        return output


    def generate_tabs_list(self):
        '''
        Return the list of item for the QListWidget

        :rtype: list
        '''
        tab_str = ""
        tabs = ["Basic", "Advanced"]
        inform_general = r"General;General (%Format%)\n"

        informs = [inform_general]
        
        if self.track_count["Video"] == 1:
            inform_video = r'Video;Video (%Format%)\n'
            informs.append(inform_video)
        elif self.track_count["Video"] > 1:
            inform_video = r'Video;Video #%StreamKindPos% (%Format%)\n'
            informs.append(inform_video)
            
        if self.track_count["Audio"] == 1:
            inform_audio = r'Audio;Audio (%Format%)\n'
            informs.append(inform_audio)
        elif self.track_count["Audio"] > 1:
            inform_audio = r'Audio;Audio #%StreamKindPos% (%Format%)\n'
            informs.append(inform_audio)

        if self.track_count["Text"] == 1:
            inform_text = r'Text;Text (%Format%)\n'
            informs.append(inform_text)
        elif self.track_count["Text"] > 1:
            inform_text = r'Text;Text #%StreamKindPos% (%Format%)\n'
            informs.append(inform_text)

        for inform in informs:
            tab_str += self.media_inform(inform)

        if not self.track_count["Menu"] == 0:
            tab_str += "Menu"

        tabs.extend(list(filter(None, tab_str.split("\n"))))
        return tabs


    def generate_tabs_content(self):
        '''
        Return the content of the tabs

        :rtype: dict[str:str]
        '''
        track_list = self.advanced_info.split("\n\n")
        del track_list[-1]

        tabs = {}
        tabs["Basic"] = self.basic_info
        tabs["Advanced"] = self.advanced_info
            

        for i in range(len(track_list)):
            tabs.update({self.tabs_list[i+2]: track_list[i]})
        
        return tabs