/* This file is part of the KDE project
   Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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 library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#include "ShapePropertiesDocker.h"
#include <KoShape.h>
#include <KoPathShape.h>
#include <KoShapeConfigWidgetBase.h>
#include <KoShapeManager.h>
#include <KoShapeFactoryBase.h>
#include <KoShapeRegistry.h>
#include <KoCanvasBase.h>
#include <KoCanvasController.h>
#include <KoSelection.h>
#include <KoParameterShape.h>
#include <KoUnit.h>

#include <klocalizedstring.h>

#include <QStackedWidget>

class ShapePropertiesDocker::Private {
public:
    Private() : widgetStack(0), currentShape(0), currentPanel(0), canvas(0) {}
    QStackedWidget * widgetStack;
    KoShape * currentShape;
    KoShapeConfigWidgetBase * currentPanel;
    KoCanvasBase * canvas;
};


ShapePropertiesDocker::ShapePropertiesDocker(QWidget *parent)
    : QDockWidget(i18n("Shape Properties"), parent),
    d( new Private() )
{
    d->widgetStack = new QStackedWidget();
    setWidget(d->widgetStack);
}

ShapePropertiesDocker::~ShapePropertiesDocker()
{
    delete d;
}

void ShapePropertiesDocker::unsetCanvas()
{
    setEnabled(false);
    d->canvas = 0;
}

void ShapePropertiesDocker::setCanvas( KoCanvasBase *canvas )
{
    setEnabled(canvas != 0);

    if (d->canvas) {
        d->canvas->disconnectCanvasObserver(this); // "Every connection you make emits a signal, so duplicate connections emit two signals"
    }

    d->canvas = canvas;

    if( d->canvas )  {
        connect( d->canvas->shapeManager(), SIGNAL(selectionChanged()),
            this, SLOT(selectionChanged()) );
        connect( d->canvas->shapeManager(), SIGNAL(selectionContentChanged()),
            this, SLOT(selectionChanged()) );
        connect( d->canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
            this, SLOT(canvasResourceChanged(int,QVariant)) );
    }
}

void ShapePropertiesDocker::selectionChanged()
{
    if( ! d->canvas )
        return;

    KoSelection *selection = d->canvas->shapeManager()->selection();
    if( selection->count() == 1 )
        addWidgetForShape( selection->firstSelectedShape() );
    else
        addWidgetForShape( 0 );
}

void ShapePropertiesDocker::addWidgetForShape( KoShape * shape )
{
    // remove the config widget if a null shape is set, or the shape has changed
    if( ! shape || shape != d->currentShape )
    {
        while( d->widgetStack->count() )
            d->widgetStack->removeWidget( d->widgetStack->widget( 0 ) );
    }

    if( ! shape )
    {
        d->currentShape = 0;
        d->currentPanel = 0;
        return;
    }
    else if( shape != d->currentShape )
    {
        // when a shape is set and is differs from the previous one
        // get the config widget and insert it into the option widget
        d->currentShape = shape;
        if( ! d->currentShape )
            return;
        QString shapeId = shape->shapeId();
        KoPathShape * path = dynamic_cast<KoPathShape*>( shape );
        if( path )
        {
            // use the path specific shape id if shape is a path, otherwise use the shape id
            shapeId = path->pathShapeId();
            // check if we have an edited parametric shape, then we use the path shape id
            KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>( shape );
            if( paramShape && ! paramShape->isParametricShape() )
                shapeId = shape->shapeId();
        }
        KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value( shapeId );
        if( ! factory )
            return;
        QList<KoShapeConfigWidgetBase*> panels = factory->createShapeOptionPanels();
        if( ! panels.count() )
            return;

        d->currentPanel = 0;
        uint panelCount = panels.count();
        for( uint i = 0; i < panelCount; ++i )
        {
            if( panels[i]->showOnShapeSelect() ) {
                d->currentPanel = panels[i];
                break;
            }
        }
        if( d->currentPanel )
        {
            if( d->canvas )
                d->currentPanel->setUnit( d->canvas->unit() );
            d->widgetStack->insertWidget( 0, d->currentPanel );
            connect( d->currentPanel, SIGNAL(propertyChanged()),
                     this, SLOT(shapePropertyChanged()));
        }
    }

    if( d->currentPanel )
        d->currentPanel->open( shape );
}

void ShapePropertiesDocker::shapePropertyChanged()
{
    if( d->canvas && d->currentPanel )
    {
        KUndo2Command * cmd = d->currentPanel->createCommand();
        if( ! cmd )
            return;
        d->canvas->addCommand( cmd );
    }
}

void ShapePropertiesDocker::canvasResourceChanged(int key, const QVariant &variant)
{
    if (key == KoCanvasResourceManager::Unit && d->currentPanel)
        d->currentPanel->setUnit(variant.value<KoUnit>());
}
