/*
 *  Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org)
 *
 *  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 2 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, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
#include <stdlib.h>
#include <vector>
#include <math.h>

#include <tqpoint.h>
#include <tqspinbox.h>
#include <tqrect.h>
#include <tqcolor.h>

#include <tdelocale.h>
#include <kiconloader.h>
#include <tdeinstance.h>
#include <tdemessagebox.h>
#include <tdestandarddirs.h>
#include <tdetempfile.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <knuminput.h>

#include <kis_debug_areas.h>
#include <kis_image.h>
#include <kis_iterators_pixel.h>
#include <kis_layer.h>
#include <kis_filter_registry.h>
#include <kis_debug_areas.h>
#include <kis_types.h>
#include <kis_paint_device.h>
#include <kis_colorspace_registry.h>

#include "kis_ws_engine_filter.h"
#include "kis_wet_sticky_colorspace.h"

/**
 * The Wet & Sticky Engine filter is based on the wet & sticky model
 * for computer painting designed by Tunde Cockshott and implemented
 * by David England and Kevin Waite.
 *
 * The filter implements the engine that moves the paint according to
 * gravity, viscosity and absorbency.
 *
 */
KisWSEngineFilter::KisWSEngineFilter() : KisFilter(id(), "", i18n("&Wet & Sticky paint engine..."))
{
}


/**
 * Sets the POINT giving the coordinate location of the next
 * cell on the canvas to be visited.  There is an even probability
 * of each cell being visited.
 */
TQPoint next_cell(TQ_UINT32 width, TQ_UINT32 height)
{
    return TQPoint(random() * width,  random() * height);
}

void single_step(KisColorSpace * cs, KisPaintDeviceSP src,  KisPaintDeviceSP dst, const TQRect & rect, bool native)
{
    using namespace WetAndSticky;


    TQPoint p = next_cell( rect.width(),  rect.height() );

    // XXX: We could optimize by randomly doing lines of 64 pixels
    // -- maybe that would be enough to avoid the windscreen wiper
    // effect.
    KisHLineIterator iter = src -> createHLineIterator(p.x(), p.y(), 1,  false);

    TQ_UINT8 *orig = iter.rawData();
    TQ_UINT8 *pix = orig;

     if (!orig) return;

    if (!native ) {
        TQColor c;
        TQ_UINT8 opacity;

        src -> colorSpace() -> toTQColor(pix, &c, &opacity);
        TQ_UINT8 *pix = new TQ_UINT8[sizeof( cell )];
        TQ_CHECK_PTR(pix);

        cs -> fromTQColor(c, opacity, pix);
    }

    // Process

    CELL_PTR c = ( CELL_PTR )pix;


    if ( !native ) {
        // Set RGBA back
    }

}

void KisWSEngineFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
{

    m_src = src;
    m_dst = dst;
    m_cfg = ( KisWSEngineFilterConfiguration * )configuration;
    m_rect = rect;


    kdDebug(DBG_AREA_FILTERS) << "WSEnginefilter called!\n";
    TQTime t;
    t.restart();

    // Two possibilities: we have our own, cool w&s pixel, and
    // then we have real data to mess with, or we're filtering a
    // boring shoup-model paint device and we can only work by
    // synthesizing w&s pixels.
    bool native = false;
    // XXX: We need a better way to ID color strategies
    if ( src -> colorSpace() -> id() == KisID("W&S","") ) native = true;

    // XXX: We need a better way to ID color strategies
    KisColorSpace * cs = KisColorSpaceRegistry::instance()->get("W&S");

    TQ_UINT32 pixels = 400; //m_cfg -> pixels();

    kdDebug(DBG_AREA_FILTERS) << "Going to singlestep " << pixels << " pixels.\n";

    // Determine whether we want an infinite loop
    if ( pixels == 0 ) {
        while ( true )
            single_step (cs, src, dst, rect, native);
    }
    // Or not.
    else {
        for ( TQ_UINT32 i = 0; i < pixels; ++i ) {
            single_step (cs, src, dst, rect, native);
        }
    }
    kdDebug(DBG_AREA_FILTERS) << "Done in " << t.elapsed() << " ms\n";

}

KisFilterConfigWidget * KisWSEngineFilter::createConfigurationWidget(TQWidget* parent, KisPaintDeviceSP dev)
{
//     KisWSEngineFilterConfigurationWidget* kefcw = new KisWSEngineFilterConfigurationWidget(this,parent, "");
//     kdDebug(DBG_AREA_FILTERS) << kefcw << endl;
//     return kefcw  ;
    return 0;
}

KisFilterConfiguration* KisWSEngineFilter::configuration(TQWidget* nwidget, KisPaintDeviceSP dev)
{
//     KisWSEngineFilterConfigurationWidget* widget = (KisWSEngineFilterConfigurationWidget*) nwidget;

//     if( widget == 0 )
//     {
//         return new KisWSEngineFilterConfiguration(30);
//     } else {
//                 TQ_UINT32 depth = widget -> baseWidget() -> depthSpinBox -> value();

//                 return new KisWSEngineFilterConfiguration(depth);
//         }


    return new KisWSEngineFilterConfiguration( m_rect.height() * m_rect.width() );
}

