from audioop import add
import os
import configparser

config = configparser.ConfigParser()
config.read('./data/settings.ini')
co = config['Dev Settings']['verbose']

if co == "True":
    pass
else:
    os.environ["KIVY_NO_CONSOLELOG"] = "1"

import signal
import time
import multiprocessing
from kivy.core.window import Window, Config
from kivy.uix.screenmanager import ScreenManager
from kivymd.uix.screen import MDScreen
from kivymd.app import MDApp
from kivy.base import Builder
from kivy.uix.popup import Popup
from kivy.clock import Clock
import bin.csv_parsers
import bin.filepathanalysis
import bin.player
import math
import bin.autocomplete
import bin.servercoms


returnOk = False
pl = bin.player.Player()
pa = bin.filepathanalysis.PathAnalysis()
cvr = bin.csv_parsers.CsvRead()
cvw = bin.csv_parsers.CsvWrite()
ac = bin.autocomplete.AutoComplete()
svc = bin.servercoms.ServerComs()
version_app = f"Music Player {config['Info']['version']}{config['Info']['subVersion']}"

global address
address = ""


###########
# Popups
###########

class AppQuitting(Popup):
    pass


class ConnectPU(Popup):
    def tryconnect(self):
        print("trying to connect")
        self.url = self.ids.url.text
        self.containsPort = False
        for self.letter in self.url:
            if self.letter == ":":
                self.containsPort = True
            else:
                pass
        self.connectionurl = ""
        if self.url[:8] != "https://" and  self.url[:7] != "http://" and self.url[len(self.url) - 1:] == "/" and not self.containsPort and len(self.url) > 2:
            self.connectionurl = f"http://{self.url[:len(self.url) - 1]}:8000"
            if svc.connect(self.connectionurl):
                self.dismiss()
            else:
                self.ids.output.text = "There was an error in connecting to the server! Please make sure that the ip is correct!"
        elif self.url[:8] != "https://" and self.url[:7] != "http://" and self.url[len(self.url) - 1:] != "/" and not self.containsPort and len(self.url) > 2:
            self.connectionurl = f"http://{self.url}:8000"
            if svc.connect(self.connectionurl):
                self.dismiss()
            else:
                self.ids.output.text = "There was an error in connecting to the server! Please make sure that the ip is correct!"
        else:
            self.ids.output.text = "Invalid address, please enter just the IP address!"
        global address
        address = self.connectionurl


class QuitPU(Popup):
    def quitapp(self):
        svc.poststatus(address, False)
        time.sleep(1)


class PathMissingPU(Popup):
    pass


class PathWrongPU(Popup):
    pass


class invalidpathPU(Popup):
    pass


class NotConnected(Popup):
    pass


class LeavePU(Popup):
    def check_pwd(self):
        if self.ids.passw.text == config["Security"]["pwd"]:
            returnOk = True
            self.dismiss()
        else:
            time.sleep(2)
            self.ids.output.text = "Password wrong, please try again!"

    def returnToFullscreen(self):
        Window.fullscreen = True


###########
# SCREENS
###########


class Home(MDScreen):
    def initapp(self):
        return version_app

    def change_screen(self):
        if self.ids.filepath.text != "":
            self.analyse_dir()
        else:
            self.openpathmpu()

    def analyse_dir(self):
        try:
            self.__fcontent = os.listdir(self.ids.filepath.text)
            self.__good_files = 0
            for self.item in self.__fcontent:
                self.__filextension = self.item[(len(self.item) - 4):]
                if self.__filextension == ".mp3" or self.__filextension == ".wav":
                    self.__good_files += 1
                else:
                    pass
            if self.__good_files > 0:
                cvw.write_str("./data/temp.csv", [self.ids.filepath.text])
                self.manager.current = "Main"
                self.manager.transition.direction = "left"
            else:
                self.openpathfpu()
        except Exception as e:
            print(e)
            self.ivpathpu()

    def openpathmpu(self):
        self.pmpu = PathMissingPU()
        self.pmpu.open()

    def openpathfpu(self):
        self.wppu = PathWrongPU()
        self.wppu.open()

    def ivpathpu(self):
        self.ivppu = invalidpathPU()
        self.ivppu.open()

    def autocomplete(self):
        self.text = self.ids.filepath.text
        self.input = self.text[len(self.text) - 1:]
        if self.input == "\t":
            self.__ac = ac.autocomplete(self.text)
            self.ids.cmd_output.text = self.__ac.pop(0)
            self.output = self.__ac.pop(0)
            Clock.schedule_once(self.reloadf, 0.1)
        else:
            pass

    def reloadf(self, dt):
        self.ids.filepath.text = self.output

    def quitapp(self):
        QuitPU().open()
    
    def connectServer(self):
        ConnectPU().open()


class Main(MDScreen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.instructions = multiprocessing.Value('i', 0)
        self.others = multiprocessing.Value('i', 0)
        self.backfeed = multiprocessing.Value('f', 0)
        self.keyboard = Window.request_keyboard(None, self)
        self.keyboard.bind(on_key_down=self.key_pressed)
        self.quit_requests = 0
        self.__comparepos = 10000
        global address

    def key_pressed(self, keyboard, keycode, text, modifiers):
        # print(keycode[1])
        self.key = keycode[1]
        if self.key == "spacebar":
            self.playmusic()
        elif self.key == "right":
            self.nextsong()
        elif self.key == "up":
            self.rewindsong()
        elif self.key == "left":
            self.previoussong()
        elif self.key == "escape":
            self.back_here()
        elif self.key == "s":
            if self.manager.current == "Main":
                self.manager.current = "Showcase"
                self.manager.transition.direction = "left"
            else:
                pass
        elif self.key == "f" and self.manager.current == "Showcase":
            if Window.fullscreen == 'auto':
                Window.fullscreen = False
            else:
                Window.fullscreen = 'auto'
                Window.maximize()
        else:
            pass

    def initialize(self):
        if address != "":
            self.ids.connectstatus.text = f"Connected to: {address}"
            svc.poststatus(address, True)
            if svc.getfullscreeninfo(address) == "True":
                self.ids.fullscreenc.text = "Exit fullscreen on client display"
            else:
                self.ids.fullscreenc.text = 'Enter fullscreen on client display'
        else:
            self.ids.connectstatus.text = "not connected to any server"
        try:
            self.refreshspeed = int(config["Performance"]["showcaseRefreshRate"])
        except ValueError:
            self.refreshspeed = 1
        try:
            Clock.schedule_interval(self.screen_updating, self.refreshspeed)
        except:
            print("Failed to schedule screen updating")

        try:
            if self.mplayer.is_alive() is True:
                pass
            else:
                cvw.chg_str("./data/config.csv", 0, 0, "0")
                self.instructions = multiprocessing.Value('i', 0)
                self.others = multiprocessing.Value('i', 0)
                self.backfeed = multiprocessing.Value('f', 0)
                self.mplayer = multiprocessing.Process(name="player", target=pl.musicmanager, args=(self.instructions, self.others, self.backfeed,))
                self.mplayer.start()
        except AttributeError:
            cvw.chg_str("./data/config.csv", 0, 0, "0")
            self.instructions = multiprocessing.Value('i', 0)
            self.others = multiprocessing.Value('i', 0)
            self.backfeed = multiprocessing.Value('f', 0)
            self.mplayer = multiprocessing.Process(name="player", target=pl.musicmanager, args=(self.instructions, self.others, self.backfeed,))
            self.mplayer.start()

    def playmusic(self):
        self.others.value = 3
        if self.instructions.value == 0:
            self.instructions.value = 1
            self.ids.pp_button.text = "Pause"
        else:
            self.instructions.value = 0
            self.ids.pp_button.text = "Play"

    def nextsong(self):
        self.others.value = 1

    def rewindsong(self):
        self.others.value = 2

    def previoussong(self):
        self.others.value = 4

    def go_back(self):
        try:
            self.mplayer.kill()
        except:
            pass
        svc.poststatus(address, False)
        self.ids.pp_button.text = "Play"
        self.manager.current = "Home"
        self.manager.transition.direction = "right"

    def screen_updating(self, waste):
        self.__windowsize = Window._get_size()
        self.__windowsize_x = self.__windowsize[0]
        self.__windowsize_y = self.__windowsize[1]
        self.__text_size = round(math.sqrt(((self.__windowsize_x + self.__windowsize_y) / 2)), 0)
        self.manager.get_screen("Showcase").ids.current_song.font_size = self.__text_size + 5
        self.manager.get_screen("Showcase").ids.upcoming_songs.font_size = self.__text_size - 5
        self.manager.get_screen("Showcase").ids.titleinfo.font_size = self.__text_size * 2.2
        self.manager.get_screen("Showcase").ids.upcoming_ind.font_size = self.__text_size + 10
        self.__config = cvr.importing("./data/config.csv").pop(0)
        self.__config.pop(1)
        self.__info = cvr.importing("./data/songtemp.csv")
        self.__currents_imp = self.__info.pop(0)
        self.__currents = int(self.__currents_imp.pop(0))
        self.__upcoming = self.__info.pop(0)
        self.__songlinfo = self.__info.pop(0)
        self.__songpos = self.backfeed.value
        self.__songlength = self.__songlinfo.pop(0)
        self.__songdisplay = int(self.__songpos / float(self.__songlength) * 100)
        self.manager.get_screen("Showcase").ids.progressbars.value = self.__songdisplay
        self.__current = self.__upcoming.pop(self.__currents)
        if self.__config == ["1"]:
            self.__current_output = self.__current[:(len(self.__current) - 4)]
        else:
            self.__current_output = self.__current
        self.ids.current_song.text = self.__current_output
        self.manager.get_screen("Showcase").ids.current_song.text = self.__current_output
        if len(self.__upcoming) <= self.__currents:
            self.__upcoming_output = "No more songs in Queue"
        else:
            self.__upcoming2 = str(self.__upcoming.pop(self.__currents))
            if self.__config == ["1"]:
                self.__upcoming_output = self.__upcoming2[:(len(self.__upcoming2) - 4)]
            else:
                self.__upcoming_output = self.__upcoming2

            self.__length_output = 0
            for i in range(len(self.__upcoming) - self.__currents):
                if self.__length_output > 5:
                    pass
                else:
                    self.__upcoming2 = str(self.__upcoming.pop(self.__currents))
                    if self.__config == ["1"]:
                        self.__upcoming_output += f"\n{self.__upcoming2[:(len(self.__upcoming2) - 4)]}"
                    else:
                        self.__upcoming_output += f"\n{self.__upcoming2}"
                    self.__length_output += 1
        self.manager.get_screen("Showcase").ids.upcoming_songs.text = self.__upcoming_output
        if address != "":
            svc.postplaybackpos(address, self.__songpos)
            if self.__comparepos > self.__songpos:
                svc.postcurrentsong(address, self.__current_output)
                svc.postsonglength(address, self.__songlength)
                svc.postupcomingsongs(address, self.__upcoming_output)
                # svc.postfullscreen(address, self.__current_output)
            else:
                pass
            self.__comparepos = self.__songpos
        else:
            pass

    def back_here(self):
        if self.manager.current == "Showcase":
            self.manager.current = "Main"
            self.manager.transition.direction = "right"
        elif self.manager.current == "Main":
            self.go_back()
        else:
            pass

    def open_leave_popup(self):
        LeavePU().open()

    def changeServerSettings(self):
        if address != "":
            svc.changefullscreen(address)
            if svc.getfullscreeninfo(address) == "True":
                self.ids.fullscreenc.text = "Exit fullscreen on client display"
            else:
                self.ids.fullscreenc.text = 'Enter fullscreen on client display'
        else:
            NotConnected().open()



class ShowcaseS(MDScreen):
    def leave_screen(self):
        self.manager.current = "Main"
        self.manager.transition.direction = "right"

    def disablefullscreen(self):
        Window.fullscreen = False

    def reset(self):
        returnOk = False


class RootScreen(ScreenManager):
    pass


class MusicPlayer(MDApp):
    def build(self):
        Window.bind(on_request_close=self.on_request_close)
        self.title = "MusicPlayer"
        self.theme_cls.primary_palette = "Blue"
        self.theme_cls.accent_palette = "Gray"
        # self.icon = "./BiogasControllerAppLogo.png"
        return Builder.load_file("./bin/gui/gui.kv")

    def on_request_close(self, *args):
        global address
        AppQuitting().open()
        print("leaving...")
        svc.poststatus(address, False)
        time.sleep(1)
        os.killpg(os.getpgid(0), signal.SIGKILL)


if __name__ == "__main__":
    if config['Display']['launchMaximized'] == "True":
        Window.maximize()
    else:
        pass
    try:
        Window.size = (int(config['Display']['width']), int(config['Display']['height']))
    except Exception as e:
        print("Unvalid config string found in Display settings")

    Config.set('graphics', 'width', '800')
    Config.set('graphics', 'height', '600')
    Config.set('graphics', 'resizable', True)
    Config.set('kivy', 'exit_on_escape', '0')
    Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
    Config.set('graphics', 'window_state', 'normal')
    Config.write()
    MusicPlayer().run()
