import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import pandas
from bs4 import BeautifulSoup
from utils.utils import WINDOWS
[docs]def dataframeToHTML(keywordsDataframe: pandas.DataFrame):
    """
    Convert input dataframe to HTML table
    Table is generated using BeautifulSoup.
    :param keywordsDataframe: keywrods dataframe
    :return: HTML page with table
    """
    html_doc = """
    <html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <!-- Bootstrap CSS -->
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
      integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
      crossorigin="anonymous"
    />
    <style>
      body,
      html {
        margin: 0; 
        height: 100%; 
        overflow: hidden;
        padding-bottom: 15px;
      }
      div, table {
        height: 100%;
        padding-bottom: 40px;
      }
      .max-cell-width {
        max-width: 350px;
      }
      .min-cell-width {
        min-width: 150px;
      }
      .table-striped tbody tr.highlight {
        background-color: lemonchiffon;
      }
    </style>
  </head>
  <body>
    <nav class="navbar navbar-expand-md navbar-dark bg-primary">
      <a class="navbar-brand mx-auto" href="#">Select trace to execute</a>
    </nav>
    <div class="container-fluid pt-3" style="padding-bottom: 10px; margin-bottom: 10px;">
      <table id="decisionTable" class="table table-sm table-responsive table-hover table-striped">
        <thead class="thead-light">
          <tr>
            <th scope="col">Case ID</th>
            <th scope="col">Category</th>
            <th scope="col">Application</th>
            <th scope="col">Events</th>
            <th scope="col">Hostname</th>
            <th scope="col">URL</th>
            <th scope="col">Keywords</th>
            <th scope="col">Path</th>
            <th scope="col">Clipboard</th>
            <th scope="col">Cells</th>
            <th scope="col">ID</th>
          </tr>
        </thead>
        <tbody>
        
        </tbody>
        </table>
    </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script
      src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
      integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
      integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
      integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
      crossorigin="anonymous"
    ></script>
        <script>
      function getSelectedTrace() {
        let caseid;
        let radios = document.getElementsByName("group1");
        for (let i = 0, length = radios.length; i < length; i++) {
          if (radios[i].checked) {
            caseid = radios[i].value;
            break;
          }
        }
        return caseid;
      }
      $("#decisionTable tr").click(function () {
        $(this).find("th input:radio").prop("checked", true);
        $(this).addClass("highlight").siblings().removeClass("highlight");
      });
    </script>
  </body>
</html>
    """
    soup = BeautifulSoup(html_doc, 'lxml')
    tbody = soup.find('tbody')
    for trace in keywordsDataframe.values:
        caseID = trace[0]
        tr = soup.new_tag('tr', attrs={"class": "cursor-pointer"})
        # radio
        th = soup.new_tag('th')
        div = soup.new_tag('div', attrs={"class": "form-check"})
        radio_input = soup.new_tag("input", attrs={"class": "form-check-input",
                                                   "name": "group1",
                                                   "type": "radio",
                                                   "value": str(caseID)})
        label = soup.new_tag('label', attrs={"class": "form-check-label"})
        label.string = str(caseID)
        div.append(radio_input)
        div.append(label)
        th.append(div)
        tr.append(th)
        # nested loop necessary to cycle through columns of the table for each row
        for column in range(1, len(trace)):  # case id is already added above
            # URL, keywords, path and clipboard columns should be wider if they have content
            if column in range(5, 9) and trace[column]:
                td = soup.new_tag('td', attrs={"class": "text-break text-wrap",
                                               "style": "min-width: 350px; max-width: 600px;"})
            else:
                td = soup.new_tag('td', attrs={"class": "text-break text-wrap min-cell-width max-cell-width"})
            value = trace[column]
            td.string = str(value)
            tr.append(td)
        tbody.append(tr)
    return soup.prettify() 
[docs]class DecisionDialogWebView(QDialog):
    """
    Decision dialog to display and choose different decision in a routine.
    The input dataframe is shown in a HTML table generated at runtime using the dataframeToHTML() function
    and displayed in a webview.
    """
[docs]    def __init__(self, df: pandas.DataFrame):
        """
        Initialize decision dialog
        :param df: keywords dataframe
        :return: caseID of selected trace
        """
        super(DecisionDialogWebView, self).__init__()
        self.setMinimumWidth(800)
        self.df = df
        self.selectedTrace = None
        self.__controls()
        self.__layout() 
    def __controls(self):
        self.browser = QWebEngineView()
        text = dataframeToHTML(self.df)
        self.browser.setHtml(text)
    def __layout(self):
        self.setWindowTitle("Decision point")
        self.browser.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        if WINDOWS:
            self.browser.setZoomFactor(1.8)
        self.vBox = QVBoxLayout()
        self.getTraceButton = QPushButton("Select trace")
        self.vBox.addWidget(self.browser)
        self.vBox.addWidget(self.getTraceButton, alignment=Qt.AlignCenter | Qt.AlignBottom)
        self.setLayout(self.vBox)
        self.getTraceButton.clicked.connect(self.updateBounds)
    def updateBounds(self):
        self.browser.page().runJavaScript("getSelectedTrace()", self.getBounds)
    def getBounds(self, trace):
        self.accept()
        self.selectedTrace = trace 
# if __name__ == '__main__':
#     from io import StringIO
#     k = StringIO(""",case:concept:name,category,application,events,hostname,url,keywords,path,clipboard,cells,id
# 0,1005090352791000,Browser,Chrome,typed,corsidilaurea.uniroma1.it,https://corsidilaurea.uniroma1.it/,,,,,
# 1,1005090509725000,Browser,Chrome,"changeField, link","www.google.com, www.uniroma1.it","https://www.google.com/, https://www.uniroma1.it/it/",uniroma1,,,,
# """)
#     df = pandas.read_csv(k, index_col=0).fillna('')
#     app = QtWidgets.QApplication(sys.argv)
#     window = DecisionDialogWebView(df)
#     window.show()
#     app.exec_()