#ifndef PASTELGFX_DRAW_FLOODFILL_HPP
#define PASTELGFX_DRAW_FLOODFILL_HPP
#include "pastel/gfx/drawing/draw_floodfill.h"
#include <vector>
namespace Pastel
{
    template <typename Type, typename Image_View>
    void floodFill(
        integer xStart, integer yStart,
        const NoDeduction<Type>& color,
        const View<2, Type, Image_View>& image)
    {
        integer width = image.width();
        integer height = image.height();
        if (xStart < 0 || xStart >= width ||
            yStart < 0 || yStart >= height)
        {
            // Seed point out of range.
            return;
        }
        using Cursor = typename Image_View::Cursor;
        const Type source = *image.cursor(xStart, yStart);
        if (source == color)
        {
            // No need to do anything.
            return;
        }
        std::vector<Integer2> stack;
        stack.push_back(Integer2(xStart, yStart));
        while (!stack.empty())
        {
            Integer2 line = stack.back();
            stack.pop_back();
            // Find the extents of this scanline
            // and draw it.
            integer xLeft = line[0];
            integer xRight = line[0];
            integer y = line[1];
            Cursor yCursor = image.cursor(xLeft, y);
            if (*yCursor != source)
            {
                continue;
            }
            {
                Cursor leftCursor = yCursor;
                leftCursor.xDecrement();
                while(xLeft > 0 && *leftCursor == source)
                {
                    *leftCursor = color;
                    --xLeft;
                    leftCursor.xDecrement();
                }
            }
            {
                Cursor xyCursor = yCursor;
                while(xRight < width && *xyCursor == source)
                {
                    *xyCursor = color;
                    ++xRight;
                    xyCursor.xIncrement();
                }
            }
            // Recurse up and down.
            if (y < height - 1)
            {
                // Recurse top line.
                bool lineHandled = false;
                integer yTop = y + 1;
                Cursor xyCursor = image.cursor(xLeft, yTop);
                for (integer x = xLeft;x < xRight;++x)
                {
                    if (*xyCursor == source)
                    {
                        if (!lineHandled)
                        {
                            stack.push_back(Integer2(x, yTop));
                            lineHandled = true;
                        }
                    }
                    else
                    {
                        lineHandled = false;
                    }
                    xyCursor.xIncrement();
                }
            }
            if (y > 0)
            {
                // Recurse bottom line.
                bool lineHandled = false;
                integer yBottom = y - 1;
                Cursor xyCursor = image.cursor(xLeft, yBottom);
                for (integer x = xLeft;x < xRight;++x)
                {
                    if (*xyCursor == source)
                    {
                        if (!lineHandled)
                        {
                            stack.push_back(Integer2(x, yBottom));
                            lineHandled = true;
                        }
                    }
                    else
                    {
                        lineHandled = false;
                    }
                    xyCursor.xIncrement();
                }
            }
        }
    }
}
#endif