#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2011, 2012                                              *  
#*   Jose Luis Cercos Pita <jlcercos@gmail.com>                            *  
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   This program is distributed in the hope that it will be useful,       *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Library General Public License for more details.                  *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with this program; if not, write to the Free Software   *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************

# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview, Plot
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry

class TaskPanel:
    def __init__(self):
        self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
        self.ship = None
        self.skip = False
        self.LSections = []
        self.BSections = []
        self.TSections = []
        self.obj = None
        self.preview = Preview.Preview()

    def accept(self):
        self.saveSections()
        self.obj = Plot.Plot(self.form.scale.value(), self.obj.Shape, self.ship.Shape)
        self.preview.clean()
        self.obj.Label = 'OutlineDraw'
        return True

    def reject(self):
        self.preview.clean()
        return True

    def clicked(self, index):
        pass

    def open(self):
        pass

    def needsFullSpace(self):
        return True

    def isAllowedAlterSelection(self):
        return False

    def isAllowedAlterView(self):
        return True

    def isAllowedAlterDocument(self):
        return False

    def helpRequested(self):
        pass

    def setupUi(self):
        mw = self.getMainWindow()
        form = mw.findChild(QtGui.QWidget, "TaskPanel")
        form.sections = form.findChild(QtGui.QTableWidget, "Sections")
        try:
            form.sections.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly)
        except:
            msg = Translator.translate("QtCore.Qt.ImhFormattedNumbersOnly not supported, will not used.\n")
            App.Console.PrintWarning(msg)
        form.sectionType = form.findChild(QtGui.QComboBox, "SectionType")
        form.deleteButton = form.findChild(QtGui.QPushButton, "DeleteButton")
        form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
        form.createButton = form.findChild(QtGui.QPushButton, "CreateButton")
        form.scale = form.findChild(QtGui.QSpinBox, "Scale")
        self.form = form
        # Initial values
        if self.initValues():
            return True
        self.retranslateUi()
        self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
        # Connect Signals and Slots
        QtCore.QObject.connect(form.sectionType,QtCore.SIGNAL("activated(QString)"),self.onSectionType)
        QtCore.QObject.connect(form.sections,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem);
        QtCore.QObject.connect(form.deleteButton,QtCore.SIGNAL("pressed()"),self.onDeleteButton)
        QtCore.QObject.connect(form.createButton,QtCore.SIGNAL("pressed()"),self.onCreateButton)

    def getMainWindow(self):
        "returns the main window"
        # using QtGui.qApp.activeWindow() isn't very reliable because if another
        # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
        # returned
        toplevel = QtGui.qApp.topLevelWidgets()
        for i in toplevel:
            if i.metaObject().className() == "Gui::MainWindow":
                return i
        raise Exception("No main window found")

    def initValues(self):
        """ Set initial values for fields
        """
        # Get selected objects
        selObjs  = Geometry.getSelectedObjs()
        if not selObjs:
            msg = Translator.translate("Ship instance must be selected (no object selected)\n")
            App.Console.PrintError(msg)
            return True
        for i in range(0,len(selObjs)):
            obj = selObjs[i]
            # Test if is a ship instance
            props = obj.PropertiesList
            try:
                props.index("IsShip")
            except ValueError:
                continue
            if obj.IsShip:
                # Test if another ship already selected
                if self.ship:
                    msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
                    App.Console.PrintWarning(msg)
                    break
                self.ship = obj
        # Test if any valid ship was selected
        if not self.ship:
            msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n")
            App.Console.PrintError(msg)
            return True
        # Load sections (if exist)
        self.loadSections()
        msg = Translator.translate("Ready to work\n")
        App.Console.PrintMessage(msg)
        return False

    def retranslateUi(self):
        """ Set user interface locale strings. 
        """
        self.form.setWindowTitle(Translator.translate("Outline draw"))
        self.form.findChild(QtGui.QGroupBox, "AutoCreateBox").setTitle(Translator.translate("Auto create"))
        self.form.findChild(QtGui.QGroupBox, "ScaleBox").setTitle(Translator.translate("Scale"))
        self.form.findChild(QtGui.QPushButton, "DeleteButton").setText(Translator.translate("Delete all sections"))
        self.form.findChild(QtGui.QPushButton, "CreateButton").setText(Translator.translate("Create sections"))
        self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(0, Translator.translate("Transversal"))
        self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(1, Translator.translate("Longitudinal"))
        self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(2, Translator.translate("Water lines"))

    def onSectionType(self):
        """ Function called when the section type is changed.
        """
        # Search section type
        ID = self.form.sectionType.currentIndex()
        self.setSectionType(ID)

    def setSectionType(self, ID):
        """ Function that set the type section related table.
        @param ID Id of the section to set: \n
        0 = Transversal sections \n
        1 = Longitudinal sections \n
        2 = Water lines
        """
        SectionList = []
        if ID == 0:
            SectionList = self.LSections[:]
        elif ID == 1:
            SectionList = self.BSections[:]
        elif ID == 2:
            SectionList = self.TSections[:]
        nRow = len(SectionList)
        self.form.sections.clearContents()
        self.form.sections.setRowCount(nRow+1)
        if not nRow:
            self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
            return
        self.skip = True                    # Avoid recursive call to OnItem
        for i in range(0,nRow):
            if i == nRow-1:
                self.skip = False
            string = '%f' % (SectionList[i])
            item = QtGui.QTableWidgetItem(string)
            self.form.sections.setItem(i,0,item)

    def onTableItem(self, row, column):
        """ Function called when an item of table is changed.
        @param row Changed item row
        @param column Changed item column
        """
        if self.skip:
            return
        # Ensure that exist one empty item at least
        nRow = self.form.sections.rowCount()
        item = self.form.sections.item(nRow-1,0)
        if item :
            if(item.text() != ''):
                self.form.sections.setRowCount(nRow+1)
        # Ensure that new item is a number
        ID = self.form.sectionType.currentIndex()
        if ID == 0:
            SectionList = self.LSections[:]
        elif ID == 1:
            SectionList = self.BSections[:]
        elif ID == 2:
            SectionList = self.TSections[:]
        item = self.form.sections.item(row,column)
        (number,flag) = item.text().toFloat()
        if not flag:
            if len(SectionList) > nRow-1:
                number = SectionList[nRow-1]
            else:
                number = 0.0
        string = '%f' % (number)
        item.setText(string)
        # Regenerate the list
        SectionList = []
        for i in range(0,nRow):
            item = self.form.sections.item(i,0)
            if item:
                (number,flag) = item.text().toFloat()
                SectionList.append(number)
        # Paste it into the class list
        ID = self.form.sectionType.currentIndex()
        if ID == 0:
            self.LSections = SectionList[:]
        elif ID == 1:
            self.BSections = SectionList[:]
        elif ID == 2:
            self.TSections = SectionList[:]
        self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
        
    def onDeleteButton(self):
        """ Function called when the delete button is pressed.
        All sections mustt be erased
        """
        self.form.sections.clearContents()
        self.form.sections.setRowCount(1)
        # Clear active list
        ID = self.form.sectionType.currentIndex()
        if ID == 0:
            self.LSections = []
        elif ID == 1:
            self.BSections = []
        elif ID == 2:
            self.TSections = []
        self.setSectionType(ID)
        
    def onCreateButton(self):
        """ Function called when create button is pressed.
        Several sections must be added to list
        """
        # Recolect data
        nSections = self.form.nSections.value()
        SectionList = []
        L = 0.0
        ID = self.form.sectionType.currentIndex()
        if ID == 0:
            L = self.ship.Length
            d = L / (nSections-1)       # Distance between sections
            start = - L/2.0         # Ship must have 0.0 at coordinates origin
        elif ID == 1:
            L = -0.5*self.ship.Beam      # Ship must be in y<0.0
            d = L / (nSections+1.0)       # Distance between sections
            start = d
        elif ID == 2:
            L = self.ship.Draft
            d = L / (nSections)       # Distance between sections
            start = d
        # Calculate sections
        for i in range(0,nSections):
            sec = i*d + start
            SectionList.append(sec)
        # Paste into class table
        if ID == 0:
            self.LSections = SectionList[:]
        elif ID == 1:
            self.BSections = SectionList[:]
        elif ID == 2:
            self.TSections = SectionList[:]
        # Print the table
        self.setSectionType(ID)

    def loadSections(self):
        """ Loads from ship object previously selected sections.
        """
        # Load sections
        props = self.ship.PropertiesList
        flag=True
        try:
            props.index("LSections")
        except ValueError:
            flag=False
        if flag:
            self.LSections = self.ship.LSections[:]
            self.BSections = self.ship.BSections[:]
            self.TSections = self.ship.TSections[:]
        # Load scale too
        flag=True
        try:
            props.index("PlotScale")
        except ValueError:
            flag=False
        if flag:
            self.form.scale.setValue(self.ship.PlotScale)
        # Set UI
        self.setSectionType(self.form.sectionType.currentIndex())

    def saveSections(self):
        """ Save selected sections into ship object.
        """
        # Test if previous section have been created
        props = self.ship.PropertiesList
        try:
            props.index("LSections")
        except ValueError:
            # Create new sections list
            self.ship.addProperty("App::PropertyFloatList","LSections","Ship", str(Translator.translate("Transversal sections position [m]"))).LSections=[]
            self.ship.addProperty("App::PropertyFloatList","BSections","Ship", str(Translator.translate("Longitudinal sections position [m]"))).BSections=[]
            self.ship.addProperty("App::PropertyFloatList","TSections","Ship", str(Translator.translate("Water lines position [m]"))).TSections=[]
        # Save sections
        self.ship.LSections = self.LSections[:]
        self.ship.BSections = self.BSections[:]
        self.ship.TSections = self.TSections[:]
        # Save also scale
        try:
            props.index("PlotScale")
        except ValueError:
            self.ship.addProperty("App::PropertyInteger","PlotScale","Ship", str(Translator.translate("Plot scale (1:scale format)"))).PlotScale=250
        self.ship.PlotScale = self.form.scale.value()

def createTask():
    panel = TaskPanel()
    Gui.Control.showDialog(panel)
    if panel.setupUi():
        Gui.Control.closeDialog(panel)
        return None
    return panel
