﻿namespace rtg.api.util
{
    using System;

    /**
     * This routine creates a 16x16 array for an ordered circular search
     * @author Zeno410
     */
    public class CircularSearchCreator
    {
        private bool active = false;
        private int size;
        private float center;

        public int[] pattern()
        {
            return pattern(12f, 16);
        }

        public int[] pattern(float maxRadius, int requestedSize)
        {
            if (active) throw new Exception();
            active = true;
            size = requestedSize;
            center = ((float)(size - 1f)) / 2f;
            int[] result = new int[size * size];
            bool[] found = new bool[size * size];
            int nextResult = 0;
            int smallerHalfSize = size / 2;
            int largerHalfSize = (size + 1) / 2;
            for (float radius = 0; radius < maxRadius; radius = radius + 0.01f)
            {
                // kind of a pain to go in a circle
                // so do a simple search in each quadrant
                // as long as the steps are really small everything will end up in order

                // upper right
                for (int y = 0; y < largerHalfSize; y++)
                {
                    for (int x = smallerHalfSize; x < size; x++)
                    {
                        int index = (int)x * size + y;
                        if (found[index]) continue;// skip to next pixel; this is already in the patter
                        float distance = distanceFromCenter(x, y);
                        if (distance > radius) continue;// still too far; skip
                                                        //place in patter
                        result[nextResult++] = index;
                        found[index] = true;
                    }
                }
                //lower right
                for (int x = size - 1; x >= smallerHalfSize; x--)
                {// out to in
                    for (int y = largerHalfSize; y < size; y++)
                    {
                        int index = (int)x * size + y;
                        if (found[index]) continue;// skip to next pixel; this is already in the patter
                        float distance = distanceFromCenter(x, y);
                        if (distance > radius) continue;// still too far; skip
                                                        //place in patter
                        result[nextResult++] = index;
                        found[index] = true;
                    }
                }
                //lower left
                for (int y = size - 1; y >= largerHalfSize - 1; y--)
                {// out to in
                    for (int x = smallerHalfSize - 1; x > -1; x--)
                    {
                        int index = (int)x * size + y;
                        if (found[index]) continue;// skip to next pixel; this is already in the patter
                        float distance = distanceFromCenter(x, y);
                        if (distance > radius) continue;// still too far; skip
                                                        //place in pattern
                        result[nextResult++] = index;
                        found[index] = true;
                    }
                }
                //upper left
                for (int x = 0; x < smallerHalfSize; x++)
                {// out to in
                    for (int y = largerHalfSize - 1; y > -1; y--)
                    {
                        int index = (int)x * size + y;
                        if (found[index]) continue;// skip to next pixel; this is already in the patter
                        float distance = distanceFromCenter(x, y);
                        if (distance > radius) continue;// still too far; skip
                                                        //place in pattern
                        result[nextResult++] = index;
                        found[index] = true;
                    }
                }
            }
            active = false;
            if (nextResult < result.Length)
            {
                int[] newResult = new int[nextResult];
                for (int i = 0; i < nextResult; i++)
                {
                    newResult[i] = result[i];
                }
                result = newResult;
            }
            return result;
        }

        float distanceFromCenter(int x, int y)
        {
            float xDist = ((float)x - center);
            float yDist = ((float)y - center);
            return (float)Math.Sqrt(xDist * xDist + yDist * yDist);
        }
    }
}