/********************************************************************************
*                                                                               *
*   Copyright (C) Golaem S.A.  All Rights Reserved.                             *
*                                                                               *
*   Original code & license:                                                    *
*                                                                               *
*   OpenSteer -- Steering Behaviors for Autonomous Characters                   *
*                                                                               *
*   Copyright (c) 2002-2003, Sony Computer Entertainment America                *
*   Original author: Craig Reynolds <craig_reynolds@playstation.sony.com>       *
*                                                                               *
*   Permission is hereby granted, free of charge, to any person obtaining a     *
*   copy of this software and associated documentation files (the "Software"),  *
*   to deal in the Software without restriction, including without limitation   *
*   the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
*   and/or sell copies of the Software, and to permit persons to whom the       *
*   Software is furnished to do so, subject to the following conditions:        *
*                                                                               *
*   The above copyright notice and this permission notice shall be included in  *
*   all copies or substantial portions of the Software.                         *
*                                                                               *
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
*   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
*   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL    *
*   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  *
*   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
*   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
*   DEALINGS IN THE SOFTWARE.                                                   *
*                                                                               *
********************************************************************************/

#pragma once

#include "glmAbstractProximityDatabase.h"
#include "glmSimuEntityHandle.h"
#include <glmPODArray.h>
#include <glmSet.h>
#include "glmSet.h"

#include <glmMutex.h>

namespace glm
{
    class Vector3;

    /** This is the "brute force" O(n^2) approach implemented in terms of the
		AbstractProximityDatabase protocol so it can be compared directly to other
		approaches.  (e.g. the Boids plugin allows switching at runtime.) */
    class BruteForceProximityDatabase : public AbstractProximityDatabase
    {
    public:
        GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

        BruteForceProximityDatabase(Simulation* simulation);
        virtual ~BruteForceProximityDatabase();
        virtual void allocateTokens(int typeIndex, int64_t count);
        virtual AbstractTokenType* getToken(int typeIndex, int64_t index);

        // the client object calls this each time its position changes
        void updateForNewPosition(AbstractTokenType* /*token*/)
        {
        }

        // find all neighbors within the given sphere (as center and radius)
        void findNeighbors(const Vector3& position, const float radius, glm::Array<SimuEntityHandle>& neighbors);

    private:
        virtual void registerToken(AbstractTokenType* token);
        virtual void unregisterToken(AbstractTokenType* token);

        //void addToken(TokenType* token);
        //void removeToken(TokenType* token);

        glm::SpinLock _lock;

        // STL vector containing all tokens in database
        GlmSet<AbstractTokenType*>::SetNodePool _groupRecyclingPool; // default alloc is a pool of 64, avoids too much allocations at once.
        GlmSet<AbstractTokenType*> _group;

        glm::PODArray<AbstractTokenType*> _allocatedTokens;
    };
} // namespace glm
