# Imports
from os.path import join, dirname
from PyQt4.uic import loadUi
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QIcon
from PyQt4.QtGui import QWidget, QTableWidgetItem, QTableWidget


class ScanView(QWidget):

    """
        This class is a view inherit from QWidget. This class managed all information related with the scan function.
    """

    def __init__(self, scanController, parent):
        """Initialize the view object and all attributes that it needs"""
        super(ScanView, self).__init__(parent)
        self.__scanController = scanController
        ui = join(dirname(__file__.split('rexploit')[0]),
                  join("rexploit", "data", "ui", "widgets", "tabs", "scan.ui"))
        loadUi(ui, self)

        # Connect buttons
        self.pushButtonScan.clicked.connect(self.pushButtonScanClicked)
        self.pushButtonCancel.clicked.connect(self.pushButtonCancelClicked)
        self.pushButtonCreateProfile.clicked.connect(self.pushButtonCreateProfileClicked)
        self.pushButtonRemoveProfile.clicked.connect(self.pushButtonRemoveProfileClicked)
        self.comboBoxProfile.currentIndexChanged.connect(self.comboBoxProfileChanged)

        # Set verticalLayout. It's resize the widget
        self.setLayout(self.verticalLayout)

        # Options for tableWidget
        self.tableWidget.setSelectionBehavior(QTableWidget.SelectRows)
        self.tableWidget.setSelectionMode(QTableWidget.SingleSelection)
        self.tableWidget.horizontalHeader().setStretchLastSection(True)
        self.tableWidget.setShowGrid(False)

        self.setProgressBarState("hide")
        self.labelStatus.setText("")

        self.setEnabledItems(False)
        self.pushButtonRemoveProfile.setEnabled(False)

    def addItem(self, row, data):
        """
        This function add a item on a row
        :param row: the row's number
        :param data: the information
        :return: None
        """

        # state can be filtered, closed or open
        # data[3] is state
        if data[3] in ["open"]:
            self.tableWidget.setVerticalHeaderItem(row, QTableWidgetItem(QIcon().fromTheme('list-add'), ''))
        else:
            self.tableWidget.setVerticalHeaderItem(row, QTableWidgetItem(QIcon().fromTheme('dialog-error'), ''))

        for i, d in enumerate(data):
            item = QTableWidgetItem(d)
            item.setFlags(Qt.ItemIsEnabled)
            self.tableWidget.setItem(row, i, item)

    def addProfiles(self, profiles):
        """
        Add all profiles to combobox Profile
        :param profiles: the profiles
        :return: None
        """
        self.comboBoxProfile.clear()
        if profiles:
            self.pushButtonRemoveProfile.setEnabled(True)
            for profile in profiles:
                self.comboBoxProfile.addItem(profile)
        else:
            self.pushButtonRemoveProfile.setEnabled(False)

    def comboBoxProfileChanged(self):
        """This function is executed when combobox profile is changed"""
        command = self.__scanController.getCommand(self.comboBoxProfile.currentText())
        self.lineEditCommand.setText(str(command))

    def getItemText(self, row, col):
        """
        Get item's name
        :param row: row's number
        :param col: col's number
        :return: item's name
        """
        return str(self.tableWidget.item(row, col).text())

    def rowColumnCount(self):
        """
        Count the number of rows and columns
        :return: row and column
        """
        return self.tableWidget.rowCount(), self.tableWidget.columnCount()

    def setEnabledItems(self, state):
        """
        Enabled or disabled some gui's elements
        :param state: False or True
        :return: None
        """
        self.comboBoxProfile.setEnabled(state)
        self.lineEditCommand.setEnabled(state)
        self.pushButtonScan.setEnabled(state)
        self.pushButtonCancel.setEnabled(state)
        self.pushButtonCreateProfile.setEnabled(state)
        self.pushButtonRemoveProfile.setEnabled(state)
        self.tableWidget.setEnabled(state)

    def setItemsScanned(self, targets):
        """
        This function loads all targets that a project file has.
        Also it is executed when thread finished his work.
        :param targets: All scanned targets
        :return: None
        """
        if targets:
            self.tableWidget.setRowCount(len(targets))
            for row, target in enumerate(targets):
                data = [target.protocol,
                        str(target.port),
                        target.name,
                        target.state,
                        "{0} {1}".format(target.product, target.version),
                        target.info]
                self.addItem(row, data)

            self.tableWidget.resizeRowsToContents()
            self.tableWidget.resizeColumnsToContents()

            self.labelStatus.setText("Found %s port(s)" % len(targets))
            self.setProgressBarState("completed")

            self.setEnabledItems(True)
            self.pushButtonCancel.setEnabled(False)

    def setProgressBarState(self, state="hide"):
        """
        Change the progressbar's state depends on state var
        :param state: "hide", "scan" or "completed
        :return: None
        """
        if state == "hide":
            self.progressBar.hide()
            self.progressBar.setRange(0, 1)
            self.progressBar.setValue(0)
        elif state == "scan":
            self.progressBar.setFormat("Scanning")
            self.progressBar.setRange(0, 0)
            self.progressBar.show()
        elif state == "completed":
            self.progressBar.setFormat("Completed")
            self.progressBar.setRange(0, 1)
            self.progressBar.setValue(1)
            self.progressBar.show()

    def setState(self, state="start"):
        """
        Change the view's configuration depends on state var
        :param state: "start" or "scan"
        :return: None
        """
        if state == "start":
            self.tableWidget.setRowCount(0)
            self.setEnabledItems(True)
            self.labelStatus.setText("")
            self.setProgressBarState("hide")
        elif state == "scan":
            self.tableWidget.setRowCount(0)
            self.setEnabledItems(False)
            self.labelStatus.setText("Scanning")
            self.pushButtonCancel.setEnabled(True)
            self.setProgressBarState("scan")

    def pushButtonCancelClicked(self):
        """This function is executed when pushButton Cancel is clicked."""
        self.__scanController.cancel()
        self.pushButtonCancel.setEnabled(False)

    def pushButtonCreateProfileClicked(self):
        """This function is executed when pushButton CreateProfile is clicked."""
        self.__scanController.createProfile()

    def pushButtonScanClicked(self):
        """This function is executed when pushButton Scan is clicked."""
        self.__scanController.start(str(self.lineEditCommand.text()))

    def pushButtonRemoveProfileClicked(self):
        """This function is executed when pushButton RemoveProfile is clicked."""
        profile = str(self.comboBoxProfile.currentText())
        self.__scanController.removeProfile(profile)
