# -*- coding: utf-8 -*-

# -----------------------------------------------------------------
# This file is a part of PAMPI project.
# Name:         PAMPI
# Copyright:    (C) 2017-2021 Pascal PETER
# Licence:      GNU General Public Licence version 3
# Website:      http://pascal.peter.free.fr/
# Email:        pascal.peter at free.fr
# -----------------------------------------------------------------
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------

"""
DESCRIPTION :
    Un dialogue "assistant" pour la génération de fichier de présentation
"""

# importation des modules utiles :
from __future__ import division, print_function
import math

# importation des modules perso :
import utils, utils_functions

# PyQt5 ou PyQt4 :
if utils.PYQT == 'PYQT5':
    from PyQt5 import QtCore, QtWidgets, QtGui
else:
    from PyQt4 import QtCore, QtGui as QtWidgets, QtGui



"""
****************************************************
    LA FENÊTRE À PROPOS
****************************************************
"""

class WizardDlg(QtWidgets.QDialog):

    def __init__(self, parent=None, locale='', icon='./images/icon.png'):
        super(WizardDlg, self).__init__(parent)
        self.main = parent

        # en-tête de la fenêtre :
        size = utils.STYLE['PM_LargeIconSize'] * 4
        logoLabel = QtWidgets.QLabel()
        logoLabel.setMaximumSize(size, size)
        logoLabel.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        iconPixmap = utils.doIcon('icon', what='PIXMAP')
        logoLabel.setPixmap(iconPixmap)
        titleText = QtWidgets.QApplication.translate(
            'main', 'File Creation Wizard')
        helpText = QtWidgets.QApplication.translate(
            'main', 
            'Select a presentation template '
            'and then use the available settings.')
        titleLabel = QtWidgets.QLabel(
            utils_functions.u(
                '<h1>{0}</h1><h3 style="color:gray;">{1}</h3>').format(titleText, helpText))
        titleGroupBox = QtWidgets.QGroupBox()
        titleLayout = QtWidgets.QHBoxLayout()
        titleLayout.addWidget(logoLabel)
        titleLayout.addWidget(titleLabel)
        titleGroupBox.setLayout(titleLayout)

        # données de la présentation :
        self.lines = ''
        self.setting = {
            'n': 10, 
            'radius': 2000, 
            'offset': 1000, 
            'cols': 5, 
            'rows': 3, 
            }
        self.models = {
            'ORDER': ('polygon', 'table', 'helix', 'carousel', ), 
            'polygon': QtWidgets.QApplication.translate('main', 'regular polygon'), 
            'table': QtWidgets.QApplication.translate('main', 'arrangement in table'), 
            'helix': QtWidgets.QApplication.translate('main', 'circular helix'), 
            'carousel': QtWidgets.QApplication.translate('main', 'carousel'), 
            }

        # réglages :
        leftLayout = QtWidgets.QVBoxLayout()
        rightLayout = QtWidgets.QVBoxLayout()
        # la liste des modèles :
        modelLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Presentation template:'))
        self.modelComboBox = QtWidgets.QComboBox()
        for model in self.models['ORDER']:
            self.modelComboBox.addItem(self.models[model], model)
        self.modelComboBox.activated.connect(self.modelChanged)
        self.index = 0
        leftLayout.addWidget(modelLabel)
        rightLayout.addWidget(self.modelComboBox)
        # nombre d'étapes :
        nLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Number of steps (not counting the title):'))
        self.nSpinBox = QtWidgets.QSpinBox()
        self.nSpinBox.setRange(1, 100)
        self.nSpinBox.setSingleStep(1)
        self.nSpinBox.setValue(self.setting['n'])
        leftLayout.addWidget(nLabel)
        rightLayout.addWidget(self.nSpinBox)
        # rayon :
        radiusLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Radius:'))
        self.radiusSpinBox = QtWidgets.QSpinBox()
        self.radiusSpinBox.setRange(100, 10000)
        self.radiusSpinBox.setSingleStep(100)
        self.radiusSpinBox.setValue(self.setting['radius'])
        leftLayout.addWidget(radiusLabel)
        rightLayout.addWidget(self.radiusSpinBox)
        # décalage :
        offsetLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Offset:'))
        self.offsetSpinBox = QtWidgets.QSpinBox()
        self.offsetSpinBox.setRange(100, 5000)
        self.offsetSpinBox.setSingleStep(100)
        self.offsetSpinBox.setValue(self.setting['offset'])
        leftLayout.addWidget(offsetLabel)
        rightLayout.addWidget(self.offsetSpinBox)
        # colonnes :
        colsLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Number of columns:'))
        self.colsSpinBox = QtWidgets.QSpinBox()
        self.colsSpinBox.setRange(1, 20)
        self.colsSpinBox.setSingleStep(1)
        self.colsSpinBox.setValue(self.setting['cols'])
        leftLayout.addWidget(colsLabel)
        rightLayout.addWidget(self.colsSpinBox)
        # rangées :
        rowsLabel = QtWidgets.QLabel(
            QtWidgets.QApplication.translate(
                'main', 'Number of rows:'))
        self.rowsSpinBox = QtWidgets.QSpinBox()
        self.rowsSpinBox.setRange(1, 20)
        self.rowsSpinBox.setSingleStep(1)
        self.rowsSpinBox.setValue(self.setting['rows'])
        leftLayout.addWidget(rowsLabel)
        rightLayout.addWidget(self.rowsSpinBox)
        # agencement de tout ça :
        configLayout = QtWidgets.QHBoxLayout()
        configLayout.addLayout(leftLayout)
        configLayout.addLayout(rightLayout)
        settingsGroupBox = QtWidgets.QGroupBox()
        settingsGroupBox.setLayout(configLayout)
        # réglages désactivés par défaut :
        widgets = (self.offsetSpinBox, self.colsSpinBox, self.rowsSpinBox, )
        for widget in widgets:
            widget.setEnabled(False)

        # pour copier seulement :
        self.copyOnlyCheckBox = QtWidgets.QCheckBox(
            QtWidgets.QApplication.translate('main', 'Copy only'))
        self.copyOnlyCheckBox.setToolTip(
            QtWidgets.QApplication.translate(
                'main', 
                'If you check this box, the result '
                'will be copied to the clipboard '
                'instead of replacing your current file'))
        self.copyOnlyCheckBox.setChecked(False)
        copyOnlyLayout = QtWidgets.QHBoxLayout()
        copyOnlyLayout.addStretch(1)
        copyOnlyLayout.addWidget(self.copyOnlyCheckBox)

        # boutons :
        okButton = QtWidgets.QPushButton(
            utils.doIcon('dialog-ok-apply'), 
            QtWidgets.QApplication.translate('main', 'Ok'))
        okButton.clicked.connect(self.accept)
        cancelButton = QtWidgets.QPushButton(
            utils.doIcon('dialog-cancel'), 
            QtWidgets.QApplication.translate('main', 'Cancel'))
        cancelButton.clicked.connect(self.close)
        buttonLayout = QtWidgets.QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(okButton)
        buttonLayout.addWidget(cancelButton)

        # mise en place :
        mainLayout = QtWidgets.QVBoxLayout()
        mainLayout.addWidget(titleGroupBox)
        mainLayout.addWidget(settingsGroupBox)
        mainLayout.addLayout(copyOnlyLayout)
        mainLayout.addStretch(1)

        mainLayout.addLayout(buttonLayout)
        self.setLayout(mainLayout)
        self.setWindowTitle(titleText)

    def modelChanged(self):
        index = self.modelComboBox.currentIndex()
        if index == self.index:
            return
        self.index = index
        model = self.models['ORDER'][self.index]
        widgets = (self.nSpinBox, self.radiusSpinBox, self.offsetSpinBox, self.colsSpinBox, self.rowsSpinBox, )
        enableds = {
            'polygon': (self.nSpinBox, self.radiusSpinBox, ), 
            'table': (self.offsetSpinBox, self.colsSpinBox, self.rowsSpinBox, ), 
            'helix': (self.nSpinBox, self.radiusSpinBox, self.offsetSpinBox, ), 
            'carousel': (self.nSpinBox, self.radiusSpinBox, ), 
            }
        for widget in widgets:
            if widget in enableds[model]:
                widget.setEnabled(True)
            else:
                widget.setEnabled(False)


    def accept(self):
        """
        """
        model = self.models['ORDER'][self.index]
        self.lines = self.doLines()
        QtWidgets.QDialog.accept(self)


    def doLines(self):
        """
        fabrication des lignes du fichier 
        d'après le modèle sélectionné et les réglages
        """

        def doStep(lines, line1, step):
            """
            mise en forme des 3 lignes d'une étape
                line1 : la ligne du step
                step : le numéro de l'étape
            """
            line2 = utils_functions.u(
                '## {0}\n'.format(step))
            line3 = utils_functions.u(
                '![](data/pampi-help/splash.png)\n\n\n')
            return utils_functions.u(
                '{0}{1}{2}{3}').format(lines, line1, line2, line3) 

        model = self.models['ORDER'][self.index]
        self.setting['n'] = self.nSpinBox.value()
        self.setting['radius'] = self.radiusSpinBox.value()
        self.setting['offset'] = self.offsetSpinBox.value()
        self.setting['cols'] = self.colsSpinBox.value()
        self.setting['rows'] = self.rowsSpinBox.value()
        decalY = 0
        lines = ''

        # le titre de la présentation
        if model == 'polygon':
            lines = utils_functions.u(
                '#  {0}.step data-scale=4{1}\n\n'
                '## {2}\n\n\n\n\n').format(
                    '{', '}', 
                    self.models[model])
        elif model == 'table':
            d = - 2 * self.setting['offset']
            lines = utils_functions.u(
                '#  {0}.step data-x={2} data-y={2} data-scale=4{1}\n\n'
                '## {3}\n\n\n\n\n').format(
                    '{', '}', 
                    d, self.models[model])
        elif model == 'helix':
            decalY = int(self.setting['offset'] * (self.setting['n'] - 1) / 2)
            lines = utils_functions.u(
                '#  {0}.step data-y={2} data-scale=4{1}\n\n'
                '## {3}\n\n\n\n\n').format(
                    '{', '}', 
                    - 2 * self.setting['offset'] - decalY, 
                    self.models[model])
        elif model == 'carousel':
            lines = utils_functions.u(
                '#  {0}.step data-y=-2000 data-scale=4{1}\n\n'
                '## {2}\n\n\n\n\n').format(
                    '{', '}', 
                    self.models[model])

        # les étapes
        if model == 'polygon':
            for i in range(self.setting['n']):
                a = -i * 2 * math.pi / self.setting['n']
                angle = round(-90 + 180 * a / math.pi)
                x = round(self.setting['radius'] * math.cos(a))
                y = round(self.setting['radius'] * math.sin(a))
                #print(i + 1, d, x, y)
                line1 = utils_functions.u(
                    '# {0}.step data-x={2} data-y={3} data-rotate={4}{1}\n').format(
                    '{', '}', 
                    x, y, angle)
                lines = doStep(lines, line1, i + 1)
        elif model == 'table':
            for row in range(self.setting['rows']):
                for col in range(self.setting['cols']):
                    x = col * self.setting['offset']
                    y = row * self.setting['offset']
                    line1 = utils_functions.u(
                        '# {0}.step data-x={2} data-y={3}{1}\n').format(
                        '{', '}', 
                        x, y)
                    lines = doStep(lines, line1, row * self.setting['cols'] + col + 1)
        elif model == 'helix':
            for i in range(self.setting['n']):
                a = -i * 2 * math.pi / self.setting['n']
                angle = round(180 * a / math.pi)
                x = - round(self.setting['radius'] * math.sin(a))
                y = i * self.setting['offset'] - decalY
                z = - round(self.setting['radius'] * math.cos(a))
                line1 = utils_functions.u(
                    '# {0}.step data-x={2} data-y={3} data-z={4} data-rotate-y={5}{1}\n').format(
                    '{', '}', 
                    x, y, z, angle)
                lines = doStep(lines, line1, i + 1)
        elif model == 'carousel':
            for i in range(self.setting['n']):
                a = -i * 2 * math.pi / self.setting['n']
                angle = round(180 * a / math.pi)
                x = round(self.setting['radius'] * math.cos(a))
                z = - round(self.setting['radius'] * math.sin(a))
                line1 = utils_functions.u(
                    '# {0}.step data-x={2} data-z={3} data-rotate-y={4}{1}\n').format(
                    '{', '}', 
                    x, z, angle)
                lines = doStep(lines, line1, i + 1)

        # l'étape overview
        if model in ('polygon', 'carousel'):
            scale = int(round(0.003 * self.setting['radius']))
        elif model == 'table':
            scale = 2 * self.setting['cols']
        elif model == 'helix':
            scale = int(round(0.002 * (self.setting['offset'] * self.setting['n'])))
        else:
            scale = 15
        if scale < 1:
            scale = 1
        lines = utils_functions.u(
            '{2}\n\n\n\n\n\n# {0}#overview .step data-scale={3}{1}\n').format(
            '{', '}', 
            lines, scale)

        return lines




