"""
Un plugin destiné à Pampi, pour insérer un lecteur audio dans l'éditeur
à la position courante du curseur.
"""

from PyQt5 import QtCore, QtWidgets, QtGui

import os, random, re
from random import randint

from ._template import Plugin as Template

from .plugin_rc import *
from .ui_audio import Ui_Dialog

### modèles de code HTML

page_template = """\
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>video</title>
    <link rel="stylesheet" href="assets/css/bootstrap.min.css">
    <style>body {{background-color: #deddda;}}</style>
  </head>
  <body class="impress-not-supported">
{html}
  </body>
</html>
"""

audio_template = """\
<div>
  <audio controls id="{ident}"
    src="{source}" 
    style="width:800px">
</div>
"""

audio_pattern = re.compile(r"""<div[^>]*>.*<audio.*\sid="(?P<ident>.*)".*\ssrc="(?P<source>[^"]*)"[^>]*>[\s\n]</div>[\s\n](<div>(?P<buttons>.*)</div>)?""", re.M|re.S)


javascript = """\
<script type="text/javascript" src="{path}assets/js/starterScript.js"></script>
"""

class AudioDialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, presentationDir, audioPath, parent = None,
                 ident="", starters=[]):
        super(AudioDialog, self).__init__(parent)
        self.setupUi(self)
        self.audioPath = audioPath
        self.ident = ident
        if not self.ident:
            self.ident = os.path.basename(audioPath)[:6].strip() + str(randint(1000, 9999))
        self.presentationDir = presentationDir
        self.posterPath = ""
        self.audioEdit.setText(audioPath)
        self.idEdit.setText(self.ident)
        self.source = audioPath
        self.addStarterButton.clicked.connect(self.addStarter)
        for s in starters:
            ident, instant, label = s
            if ident == self.ident:
                self.addStarter(False, instant = float(instant), name = label.strip())
        self.showAudio()
        return

    def addStarter(self, ev, instant = None, name= None):
        """
        Ajoute un bouton de départ, compte tenu de l'indication de l'instant
        """
        if instant == None:
            instant = self.timeSpinBox.seconds()
        if name == None: name = self.starterEdit.text()
        if not name:
            name = QtCore.QCoreApplication.translate("main","Unnamed")
        b = QtWidgets.QPushButton(
            QtGui.QIcon(":/img/icons/dialog-close.png"),
            "{} ({})".format(name, instant))
        if not self.starterArea.layout():
            layout = QtWidgets.QHBoxLayout(self.starterArea)
        layout = self.starterArea.layout()
        # callback pour effacer le bouton
        def callback():
            layout.removeWidget(b)
            b.deleteLater()
            b.destroyed.connect(self.showAudio)
            return
        b.clicked.connect(callback)
        b.time = instant
        b.name = name
        b.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                              QtWidgets.QSizePolicy.Maximum))
        layout.addWidget(b)
        self.starterEdit.setText("")
        QtCore.QTimer.singleShot(0, self.showAudio)
        return
        
    def starters(self):
        """
        Renvoie la liste des boutons de départ vidéo
        courante
        """
        result = self.starterArea.findChildren(QtWidgets.QPushButton)
        return result
    
    def posterChanged(self):
        self.posterPath = self.posterEdit.text()
        self.showAudio()
        return

    def showAudio(self):
        poster = ""
        if self.posterPath:
            poster = "poster='{}'".format(
                os.path.join(self.presentationDir, self.posterPath))
        html = audio_template.format(
            ident = self.ident,
            source = os.path.join(self.presentationDir,self.source),
        )
        js = javascript.format(path = self.presentationDir + "/")
        html = page_template.format(html =  js + html + self.startersDiv())
        baseUrl = QtCore.QUrl("file://" + self.presentationDir)
        self.webView.page().setHtml(html, baseUrl)
        return

    def startersDiv(self, **dictionary):
        if "ident" in dictionary:
            ident = dictionary["ident"]
        else:
            ident=self.ident
        starters = self.starters()
        """
        fabrique le DIV avec les boutons de démarrage
        """
        startersCode = [
            """\
<button onclick ="timecode('{ident}',{time})">
  {name}
</button>
""".format(ident = ident, name = b.name, time = b.time)
            for b in starters
        ]
        startersCode = """\
<div>
{}
</div>
""" .format("".join(startersCode))
        return startersCode
    
        

class Plugin(Template):
    """
    Le constructeur prend comme paramètre la fenêtre principale
    de l'application. Il doit définir les propriété name et action
    @param mainWindow la fenêtre pincipale
    """
    def __init__(self, mainWindow):
        iconPath = ":/img/icons/audio.png"
        title = QtCore.QCoreApplication.translate(
            "main","Insert an audio track")
        Template.__init__(self, mainWindow,
                          name = "audio", iconPath = iconPath, title = title)
        return

    def _run(self):
        """
        Fonction de rappel pour le plugin
        """
        thedir = self.dataDir
        fragment = self.getSelected()
        m = audio_pattern.search(fragment)
        # si ça matche, les groupes suivants sont définis :
        # 'ident', 'source', 'buttons'
        if m:
            thedir = os.path.join(
                self.presentationsDir, os.path.dirname(m.group("source")))
        fn, _ = QtWidgets.QFileDialog.getOpenFileName(
            self.parent,
            QtCore.QCoreApplication.translate("main","Open Audio File"),
            thedir,
            QtCore.QCoreApplication.translate("main","Audios (*.wav *.ogg *.mp3 *.m4a *.wma)"));
        
        if fn:
            dictionary = {
                "source": self.simplifyDir(fn),
            }
            name, ext = os.path.splitext(fn)
            ad = AudioDialog(
                presentationDir = self.presentationsDir,
                audioPath = self.simplifyDir(fn),
                parent = self.parent,
                ident = m.group("ident") if m else "",
                starters = self.buttonsToTuples(m.group("buttons")) if m else []            )
            self.audioDialog = ad
            ok = ad.exec_()
            if ok:
                dictionary["ident"] = ad.idEdit.text()
                self.insertSelected(
                    audio_template.format(**dictionary) + ad.startersDiv(**dictionary))
        return

    def buttonsToTuples(self, text):
        """
        analyse du code Markdonw qui donne des boutons, pour y trouver
        des "starter" ; renvoie une liste. Pour chaque starter il y a
        un tuple identifiant, durée, label
        """
        buttons = re.findall("<button[^>]*>[^<]*</button>", text, re.M)
        starters=[]
        for b in buttons:
            m = re.match(r"""<button onclick ="timecode\('(.*)',(\d+.\d+)\)">[\s\n]*([^<]*)</button>""", b, re.M)
            if m :
                starters.append(m.groups())
        return starters

