"""
Un plugin destiné à Pampi, pour insérer une vidéo 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_video 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>
"""

video_template = """\
<div class="figure">
  <video id="{ident}" controls allowfullscreen class="embed-responsive-item" {poster}>
    <source src="{source}" type="{thetype}">
  </video>
</div>

"""
video_pattern = re.compile(r"""<div class="figure">.*<video id="(?P<ident>[^"]*).*class="(?P<theclass>[^"]*)"\s*(poster="(?P<poster>[^"]*)")?.*<source src="(?P<source>[^"]*)".*</video>[^<]*</div>[^<]*(<div>(?P<buttons>.*)</div>)?""", re.M|re.S)

style_video_400x300 = """\
<style type="text/css">
  video{
    width: 400px;
    height: 300px;
  }
</style>
"""

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

class VideoDialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, presentationDir, videoPath, parent = None,
                 ident="", posterPath="", starters=[]):
        super(VideoDialog, self).__init__(parent)
        self.setupUi(self)
        self.videoPath = videoPath
        self.ident = ident
        if not self.ident:
            self.ident = os.path.basename(videoPath)[:6].strip() + str(randint(1000, 9999))
        self.presentationDir = presentationDir
        self.posterPath = posterPath
        self.posterEdit.setText(posterPath)
        self.videoEdit.setText(videoPath)
        self.idEdit.setText(self.ident)
        self.source = videoPath
        self.thetype = "video/{}".format(os.path.splitext(videoPath)[1][1:])
        self.posterEdit.textChanged.connect(self.posterChanged)
        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.showVideo()
        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.showVideo)
            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.showVideo)
        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.showVideo()
        return

    def showVideo(self):
        poster = ""
        if self.posterPath:
            poster = "poster='{}'".format(
                os.path.join(self.presentationDir, self.posterPath))
        html = video_template.format(
            ident = self.ident,
            poster = poster,
            source = os.path.join(self.presentationDir,self.source),
            thetype = self.thetype
        )
        js = javascript.format(path = self.presentationDir + "/")
        html = page_template.format(html =  js + style_video_400x300 + 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/video.png"
        title = QtCore.QCoreApplication.translate(
            "main","Insert a video")
        Template.__init__(self, mainWindow,
                          name = "video", iconPath = iconPath, title = title)
        return

    def _run(self):
        """
        Fonction de rappel pour le plugin
        """
        thedir = self.dataDir
        fragment = self.getSelected()
        m = video_pattern.search(fragment)
        # si ça matche, les groupes suivants sont définis :
        # 'ident', 'theclass', 'poster', '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 Video File"),
            thedir,
            QtCore.QCoreApplication.translate("main","Videos (*.webm *.mkv *.ogv *.avi *.mov *.wmv *.mp4 *.m4v *.mpg)"));
        
        if fn:
            dictionary = {"source": self.simplifyDir(fn)}
            name, ext = os.path.splitext(fn)
            vd = VideoDialog(
                presentationDir = self.presentationsDir,
                videoPath = self.simplifyDir(fn),
                parent = self.parent,
                ident = m.group("ident") if m else "",
                posterPath = m.group("poster") if m else "",
                starters = self.buttonsToTuples(m.group("buttons")) if m else [],
            )
            vd.posterButton.clicked.connect(self.choose_poster)
            self.videoDialog = vd
            ok = vd.exec_()
            if ok:
                dictionary["thetype"] = "video/"+ext[1:]
                dictionary["ident"] = vd.idEdit.text()
                poster = vd.posterEdit.text()
                if poster:
                    dictionary["poster"] = 'poster="{}"'.format(poster)
                else:
                    dictionary["poster"] = ""
                self.insertSelected(
                    video_template.format(**dictionary) + vd.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

    def choose_poster(self):
        dataDir = os.path.join(self.parent.presentationsDir, "data")
        poster = self.videoDialog.posterEdit.text()
        if poster:
            dataDir = os.path.join(
                self.parent.presentationsDir, os.path.dirname(poster))
        fn, _ = QtWidgets.QFileDialog.getOpenFileName(
            self.parent,
            QtCore.QCoreApplication.translate("main","Open Poster Image File"),
            dataDir,
            QtCore.QCoreApplication.translate("main","Images (*.png *.xpm *.jpg *.jpeg)"));
        if fn:
            self.videoDialog.posterEdit.setText(self.simplifyDir(fn))
        return fn
    
