#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;


bool generateDiamondMethod1 (const int &height)
{
    static const int width = 1024;
    //an initial seed value for the corners of the data
    float SEED = 0.0f;
    static const unsigned int DATA_SIZE=width+1;
    std::vector< std::vector<float> > diamond( DATA_SIZE, std::vector<float>(DATA_SIZE) );
    //float diamond[DATA_SIZE][DATA_SIZE];

    //initialise the values of the corners++
    diamond[0][0] = SEED;
    diamond[0][DATA_SIZE-1] = SEED;
    diamond[DATA_SIZE-1][0] = SEED;
    diamond[DATA_SIZE-1][DATA_SIZE-1] = SEED;

    float h =200; 	//the range (-h -> h) for the average offset
    srand(512);		//seed the random generator

    //side length is the distance of a single square side
    //or distance of diagonal in diamond
    //each iteration we are looking at smaller squares and diamonds, we decrease the variation of the offset
    for (int sideLength = DATA_SIZE-1; sideLength >= 2; sideLength /= 2, h /= 2.0)
    {

        int halfSide = sideLength/2;

        //generate new square values
        for(int x=0; x<DATA_SIZE-1; x+=sideLength)
        {
            for(int y=0; y<DATA_SIZE-1; y+=sideLength)
            {

                //x,y is upper left corner of the square
                //calculate average of existing corners
                float avg = diamond[x][y] + 				//top left
                            diamond[(x+sideLength)%DATA_SIZE][y]   +				//top right
                            diamond[x][ (y+sideLength)%DATA_SIZE]   + 				//lower left
                            diamond[(x+sideLength)%DATA_SIZE][(y+sideLength)%DATA_SIZE]; 	//lower right

                avg /= 4.0;

                //center is average plus random offset in the range (-h, h)
                float offset = (-h) + (float)rand() * (h - (-h))  / RAND_MAX;

                diamond[x+halfSide][y+halfSide] = avg + offset;

            } //for y
        } // for x

        //Generate the diamond values
        //Since diamonds are staggered, we only move x by half side
        //NOTE: if the data shouldn't wrap the x < DATA_SIZE and y < DATA_SIZE
        for (int x=0; x<DATA_SIZE-1; x+=halfSide)
        {
            for (int y=(x+halfSide)%sideLength; y<DATA_SIZE-1; y+=sideLength)
            {

                //x,y is center of diamond
                //we must use mod and add DATA_SIZE for subtraction
                //so that we can wrap around the array to find the corners

                float avg =
                    diamond[(x-halfSide+DATA_SIZE)%DATA_SIZE][y] +	//left of center
                    diamond[(x+halfSide)%DATA_SIZE][y]				+	//right of center
                    diamond[x][(y+halfSide)%DATA_SIZE]				+	//below center
                    diamond[x][(y-halfSide+DATA_SIZE)%DATA_SIZE];	//above center

                avg /= 4.0;

                //new value = average plus random offset
                //calc random value in the range (-h,+h)
                float offset = (-h) + (float)rand() * (h - (-h))  / RAND_MAX;

                avg = avg + offset;

                //update value for center of diamond
                diamond[x][y] = avg;

                //wrap values on the edges
                //remove this and adjust loop condition above
                //for non-wrapping values
                if (x == 0) diamond[DATA_SIZE-1][y] = avg;
                if (y == 0) diamond[x][DATA_SIZE-1] = avg;
            } //for y
        } //for x
    } //for sideLength


    cout << "\r\nData Size " << DATA_SIZE;
    cout << "\r\nImage Size " << width << "x" << width;
    cout << "\r\nLocation1 "<< diamond[305][742];
    cout << "\r\nLocation2 " <<diamond[288][732];

    /// Set maxY and minY to 0.0f
    float maxY = diamond[1][1];
    float minY = diamond[1][1];

    cout << "\r\nMinimumY " << minY;
    cout << "\r\nMaximumY " << maxY;

    cout << "(Loop to find highest and new minimum)";

    for (int x = 0; x<DATA_SIZE; x++)
    {
        for(int y = 0; y<DATA_SIZE; y++)
        {
            if ((float)diamond[x][y] > maxY)
            {
                maxY = diamond[x][y];
            }
            if ((float)diamond[x][y] < minY)
            {
                minY = diamond[x][y];
            }
        }
    }

    cout << "\r\nMinimumY " << minY;
    cout << "\r\nMaximumY " << maxY << "\r\n";

    /// Calculate height from 0 to 1
    for(int x=0; x < DATA_SIZE; x++)
    {
        for(int y=0; y < DATA_SIZE; y++)
        {
            //change range to 0..1
            diamond[x][y] = (diamond[x][y] - minY) / (maxY - minY);
        }

    }

    /// Copy color float from create texture
    for(unsigned y = 0; y<width; y++)
    {
        for(unsigned x = 0; x<height; x++)
        {
            /// incremennt memory which seems to work
            int index = (y*width)+x;

            //buffer[index]=diamond[x][y];
        }
    }

    return true;
}

int main()
{
    generateDiamondMethod1(1024);
}