#
##
##  This file is part of pyFormex 1.0.2  (Thu Jun 18 15:35:31 CEST 2015)
##  pyFormex is a tool for generating, manipulating and transforming 3D
##  geometrical models by sequences of mathematical operations.
##  Home page: http://pyformex.org
##  Project page:  http://savannah.nongnu.org/projects/pyformex/
##  Copyright 2004-2015 (C) Benedict Verhegghe (benedict.verhegghe@feops.com)
##  Distributed under the GNU General Public License version 3 or later.
##
##  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/.
##
"""Viewport Menu.

This module defines the functions of the Viewport menu.
"""
from __future__ import absolute_import, division, print_function

from gettext import gettext as _

import pyformex as pf
from pyformex import utils
from pyformex.gui import widgets, draw
from pyformex.opengl import canvas
from pyformex.gui.draw import _I
from .Settings import updateSettings


def setTriade():
    try:
        pos = pf.canvas.triade.pos
        size = pf.canvas.triade.size
    except:
        pos = 'lb'
        size = 50
    res = draw.askItems([
        _I('triade', True),
        _I('pos', pos, choices=['lt', 'lc', 'lb', 'ct', 'cc', 'cb', 'rt', 'rc', 'rb']),
        _I('size', size),
        ])
    if res:
        draw.setTriade(res['triade'], res['pos'], res['size'])


def setGrid():
    res = draw.askItems([
        _I('grid', True, text='Show grid'),
        _I('d', 100, text='Distance between grid lines'),
        _I('s', 0, text='Total grid size (0=canvas size)'),
        _I('lw',1, text='Line width'),
        _I('lc','black',itemtype='color',text='Line color'),
        _I('ontop', False),
        ])
    if res:
        s = res['s'] if res['s'] >= 1 else None
        draw.setGrid(on=res['grid'],d=res['d'],s=s,linewidth=res['lw'],ontop=res['ontop'],color=res['lc'],lighting=False)


def setBgColor():
    """Interactively set the viewport background colors."""
    global bgcolor_dialog
    from pyformex.opengl.sanitize import saneColorArray
    from numpy import resize
    from pyformex.opengl import colors
    import os
    bgmodes = pf.canvas.settings.bgcolor_modes
    mode = pf.canvas.settings.bgmode
    color = saneColorArray(pf.canvas.settings.bgcolor, (4,))
    color = resize(color, (4, 3))
    cur = pf.canvas.settings.bgimage
    showimage = os.path.exists(cur)
    if not showimage:
        cur = pf.cfg['gui/splash']
    viewer = widgets.ImageView(cur, maxheight=200)

    def changeColor(field):
        bgcolor_dialog.acceptData()
        res = bgcolor_dialog.results
        if res:
            setBackground(**res)

    bgcolor_dialog = widgets.InputDialog(
        [
            _I('mode', mode, choices=bgmodes),
            _I('color1', color[0], itemtype='color', func=changeColor, text='Background color 1 (Bottom Left)'),
            _I('color2', color[1], itemtype='color', func=changeColor, text='Background color 2 (Bottom Right)'),
            _I('color3', color[2], itemtype='color', func=changeColor, text='Background color 3 (Top Right)'),
            _I('color4', color[3], itemtype='color', func=changeColor, text='Background color 4 (Top Left'),
            _I('showimage', showimage, text='Show background image'),
            _I('image', cur, text='Background image', itemtype='filename', filter='img', exist=True, preview=viewer),
            viewer,
            _I('_save_', False, text='Save as default'),
            ],
        caption='Config Dialog',
        enablers=[
            ('mode', 'vertical', 'color4'),
            ('mode', 'horizontal', 'color2'),
            ('mode', 'full', 'color2', 'color3', 'color4'),
            ('showimage', True, 'image'),
            #('mode', 'solid', '_save_'),
           ]
        )
    res = bgcolor_dialog.getResults()
    if res:
        setBackground(**res)


def setBackground(mode, color1, color2, color3, color4, showimage, image, _save_):
    if mode == 'solid':
        color = color1
    elif mode == 'vertical':
        color = [color1, color1, color4, color4]
    elif mode == 'horizontal':
        color = [color1, color2, color2, color1]
    else:
        color = [color1, color2, color3, color4]
    if not showimage:
        image = ''
    pf.canvas.setBackground(color=color, image=image)
    pf.canvas.update()
    if _save_:
        updateSettings({
            'canvas/bgmode':mode,
            'canvas/bgcolor':color,
            'canvas/bgimage':image,
            '_save_':_save_})


def setFgColor():
    """Change the default drawing color."""
    color = pf.canvas.settings.fgcolor
    color = widgets.getColor(color)
    if color:
        pf.canvas.setFgColor(color)


def setSlColor():
    """Change the highlighting color."""
    color = pf.canvas.settings.slcolor
    color = widgets.getColor(color)
    if color:
        pf.canvas.setSlColor(color)



def setLineWidth():
    """Change the default line width."""
    res = draw.askItems(
        [_I('Line Width', pf.canvas.settings.linewidth)],
        'Choose default line width'
        )
    if res:
        pf.canvas.setLineWidth(res['Line Width'])


def setCanvasSize():
    """Save the current viewport size"""
    res = draw.askItems([
        _I('w', pf.canvas.width()),
        _I('h', pf.canvas.height())
        ], caption='Set Canvas Size'
        )
    if res:
        draw.canvasSize(res['w'], res['h'])


def canvasSettings():
    """Interactively change the canvas settings.

    Creates a dialog to change the canvasSettings of the current or any other
    viewport
    """

    dia = None

    def close():
        dia.close()


    def getVp(vp):
        """Return the vp corresponding with a vp choice string"""
        if vp == 'current':
            vp = pf.GUI.viewports.current
        elif vp == 'focus':
            vp = pf.canvas
        else:
            vp = pf.GUI.viewports.all[int(vp)]
        return vp


    def accept(save=False):
        dia.acceptData()
        res = dia.results
        vp = getVp(res['viewport'])
        pf.debug("Changing Canvas settings for viewport %s to:\n%s"%(pf.GUI.viewports.viewIndex(vp), res), pf.DEBUG.CANVAS)
        pf.canvas.settings.update(res, strict=False)
        pf.canvas.redrawAll()
        pf.canvas.update()
        if save:
            res = utils.prefixDict(res, 'canvas/')
            print(res)
            res['_save_'] = save
            del res['canvas/viewport']
            updateSettings(res)

    def acceptAndSave():
        accept(save=True)

    def changeViewport(vp):
        if vp == 'current':
            vp = pf.GUI.viewports.current
        elif vp == 'focus':
            vp = pf.canvas
        else:
            vp = pf.GUI.viewports.all[int(vp)]
        dia.updateData(vp.settings)

    canv = pf.canvas
    vp = pf.GUI.viewports
    pf.debug("Focus: %s; Current: %s" % (canv, vp), pf.DEBUG.CANVAS)
    s = canv.settings

    dia = widgets.InputDialog(
        caption='Canvas Settings',
        store=canv.settings,
        items=[
            _I('viewport', choices=['focus', 'current']+[str(i) for i in range(len(pf.GUI.viewports.all))], onselect=changeViewport),
            _I('pointsize',),
            _I('linewidth',),
            _I('linestipple',),
            _I('fgcolor', itemtype='color'),
            _I('slcolor', itemtype='color'),
            _I('smooth'),
            _I('fill'),
            _I('lighting'),
            _I('culling'),
            _I('alphablend'),
            _I('transparency', min=0.0, max=1.0),
            _I('avgnormals',),
            ],
        enablers =[
            ('alphablend', ('transparency')),
            ],
        actions=[
            ('Close', close),
            ('Apply and Save', acceptAndSave),
            ('Apply', accept),
            ],
        )
    #dia.resize(800,400)
    dia.show()


def viewportLayout():
    """Interactively set the viewport layout.

    Creates a dialog that allows the user to set the viewport layout.
    If the user accepts valid data, the viewport layout is changed
    accordingly. The contents of existing viewports remaining in the
    new layout is retained.
    """
    nvps = len(pf.GUI.viewports.all)
    directions = [ 'rowwise', 'columnwise' ]
    curdir = 0 if pf.GUI.viewports.rowwise else 1
    ncols = pf.GUI.viewports.ncols
    nrows = (nvps+ncols-1) // ncols
    if curdir == 1:
        nrows,ncols = ncols,nrows
    res = draw.askItems([
        _I('nvps',nvps,text='Number of viewports'),
        _I('dir',directions[curdir],text='Layout direction',choices=directions),
        _I('ncols',ncols,text='Number of columns'),
        _I('nrows',nrows,text='Number of rows'),
    ], enablers=[('dir',directions[0],'ncols'),('dir',directions[1],'nrows')
    ], caption='Viewport Config Dialog')

    if res:
        nvps = res['nvps']
        rowwise = directions.index(res['dir']) == 0
        if rowwise:
            ncols = res['ncols']
            nrows = None
        else:
            ncols = None
            nrows = res['nrows']
        pf.GUI.viewports.changeLayout(nvps, ncols, nrows)


def drawOptions(d={}):
    """Set the Drawing options.

    A dictionary may be specified to override the current defaults.
    """
    draw.setDrawOptions(d)
    print(pf.canvas.drawoptions)
    res = draw.askItems(store=pf.canvas.drawoptions, items=[
        _I('view', choices=['None']+[k for k in pf.canvas.view_angles], tooltip="Camera viewing direction"),
        _I('bbox', choices=['auto', 'last'], tooltip="Automatically focus/zoom on the last drawn object(s)"),
        _I('clear_', tooltip="Clear the canvas on each drawing action"),
        _I('shrink', tooltip="Shrink all elements to make their borders better visible"),
        _I('shrink_factor'),
#        _I('marksize'),
        ], enablers=[('shrink', True, 'shrink_factor')]
    )
    if not res:
        return
    if res['view'] == 'None':
        res['view'] = None
    draw.setDrawOptions(res)


def cameraSettings():
    from pyformex.plugins import cameratools
    cameratools.showCameraTool()


def openglSettings():
    dia = None
    def apply_():
        dia.acceptData()
        canvas.glSettings(dia.results)
    def close():
        dia.close()

    dia = widgets.InputDialog(
        caption='OpenGL Settings',
        items=[
            _I('Line Smoothing', 'Off', itemtype='radio', choices=['On', 'Off']),
            _I('Polygon Mode', None, itemtype='radio', choices=['Fill', 'Line']),
            _I('Polygon Fill', None, itemtype='radio', choices=['Front and Back', 'Front', 'Back']),
            _I('Culling', 'Off', itemtype='radio', choices=['On', 'Off']),
# These are currently set by the render mode
#            ('Shading',None,'radio',{'choices':['Smooth','Flat']}),
#            ('Lighting',None,'radio',{'choices':['On','Off']}),
            ],
        actions=[('Done', close), ('Apply', apply_)]
        )
    dia.show()

def lineSmoothOn():
    canvas.glLineSmooth(True)

def lineSmoothOff():
    canvas.glLineSmooth(False)

def singleViewport():
    draw.layout(1)


def clearAll():
    for vp in pf.GUI.viewports.all:
        vp.removeAll()
        vp.clearCanvas()
        vp.update()
    pf.GUI.processEvents()


def showObjectDialog(show=True):
    """Show the object dialog for the current scene.


    """
    from pyformex.opengl import objectdialog
    dia = objectdialog.objectDialog(pf.canvas.actors)
    if dia and show:
        dia.show()
    return dia



MenuData = (_('&Viewport'), [
    (_('&Clear'), draw.clear),
    (_('&Clear All'), clearAll),
    (_('&Axes Triade'), setTriade),
    (_('&Canvas Grid'), setGrid),
    #        (_('&Transparency'),setOpacity),
    (_('&Background Color'), setBgColor),
    (_('&Foreground Color'), setFgColor),
    (_('&Highlight Color'), setSlColor),
    (_('Line&Width'), setLineWidth),
    (_('&Canvas Size'), setCanvasSize),
    (_('&Canvas Settings'), canvasSettings),
    (_('&Global Draw Options'), drawOptions),
    (_('&Camera Settings'), cameraSettings),
    (_('&OpenGL Settings'), openglSettings),
    ## ('&OpenGL Settings',
    ##  [('&Flat',canvas.glFlat),
    ##   ('&Smooth',canvas.glSmooth),
    ##   ('&Culling',canvas.glCulling),
    ##   ('&No Culling',canvas.glNoCulling),
    ##   ('&Line Smoothing On',lineSmoothOn),
    ##   ('&Line Smoothing Off',lineSmoothOff),
    ##   ('&Polygon Line',canvas.glLine),
    ##   ('&Polygon Fill',canvas.glFill),
    ##   ('&Polygon Front Fill',canvas.glFrontFill),
    ##   ('&Polygon Back Fill',canvas.glBackFill),
    ##   ('&Polygon Front and Back Fill',canvas.glBothFill),
    ##   ]),
    (_('&Redraw'), draw.redraw),
    (_('&Object Dialog'), showObjectDialog),
    (_('&Reset viewport'), draw.reset),
    (_('&Reset layout'), singleViewport),
    (_('&Change viewport layout'), viewportLayout),
    (_('&Add new viewport'), draw.addViewport),
    (_('&Remove last viewport'), draw.removeViewport),
    ])


# End
