
#include <iostream>
#include <stdexcept>
#include <string>
#include "geoma/geoma.h"
#include "geoma/geomaData.h"

extern "C" {
    #include <stdlib.h>
};

#define CNTR_CUTOFF	32

static double
magnitude( nklein::GeometricAlgebra< double, 3 >& z )
{
    double mag = 0.0;

    for ( unsigned int ii=0; ii < 4; ++ii ){
	double coef = z[ii];
	mag += coef * coef;
    }

    return mag;
}

    
int
main( int argc, const char* argv[] )
{
    unsigned int ww = 128;
    unsigned int hh = 128;
    double x0 = -1.75;
    double y0 =  1.75;
    double x1 =  1.75;
    double y1 = -1.75;
    unsigned int xi = 0;
    unsigned int yi = 3;

    for ( unsigned int ii=1; ii < argc; ++ii ) {
	string arg = argv[ii];

	if ( arg == "-size" ) {
	    ww = strtoul( argv[++ii], 0, 0 );
	    hh = strtoul( argv[++ii], 0, 0 );
	} else if ( arg == "-region" ) {
	    x0 = strtod( argv[++ii], 0 );
	    y0 = strtod( argv[++ii], 0 );
	    x1 = strtod( argv[++ii], 0 );
	    y1 = strtod( argv[++ii], 0 );
	} else if ( arg == "-indices" ) {
	    xi = strtoul( argv[++ii], 0, 0 );
	    yi = strtoul( argv[++ii], 0, 0 );
	} else {
	    cerr << "Unknown argument " << arg << endl;
	    cerr << "Usage: " << argv[0] << endl
		<< "      [-size w h]" << endl
		<< "      [-region x0 y0 x1 y1]" << endl
		<< "      [-indices xi yi]" << endl
		;
	    return __LINE__;
	}
    }

    cout << "P5" << endl;
    cout << ww << " " << hh << endl;
    cout << 255 << endl;

    for ( unsigned int jj=0; jj < hh; ++jj ) {
	for ( unsigned int ii=0; ii < ww; ++ii ) {
	    nklein::GeometricAlgebra< double, 3 > c;

	    c[ xi ] = ( (double) ii / (double) ww ) * (x1 - x0) + x0;
	    c[ yi ] = ( (double) jj / (double) hh ) * (y1 - y0) + y0;

	    nklein::GeometricAlgebra< double, 3 > z( c );
	    unsigned int cntr = 0;

	    while ( cntr < CNTR_CUTOFF && magnitude( z ) < 100.0 ) {
		z = ( z * z ) + c;
		++cntr;
	    }

	    unsigned char ch = 0;

	    if ( cntr < CNTR_CUTOFF ) {
		ch = (unsigned char)( 255 - 200 * cntr / (CNTR_CUTOFF-1) );
	    }

	    cout << ch;
	}
    }

    return 0;
}

