/*
 * (C) Copyright 1996- ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

#ifndef BSPNode_H
#define BSPNode_H

#include "BSPHyperPlane.h"

namespace eckit {

template<class Traits, class Partition>
class BSPNode : public SPNode<Traits, BSPNode<Traits, Partition> > {
public:


    typedef SPNode<Traits, BSPNode<Traits, Partition> > SPNodeType;
    typedef typename SPNodeType::Value     Value;
    typedef typename SPNodeType::Alloc     Alloc;
    typedef typename SPNodeType::Point     Point;
    typedef typename SPNodeType::NodeList  NodeList;
    typedef typename SPNodeType::NodeQueue NodeQueue;
    typedef typename SPNodeType::NodeInfo  NodeInfo;

    typedef BSPHyperPlane<Point>        HyperPlane;

    typedef BSPNode<Traits, Partition> Node;

private:

    HyperPlane plane_;

    double dist_; // Distance to parent's hyperplane

public:

    BSPNode(const Value& v, const HyperPlane& plane, double dist);
    virtual ~BSPNode() {}

    template<typename Container>
    static BSPNode* build(Alloc& a, Partition& p, const Container& nodes, double dist, int depth = 0);


private:
    virtual void nearestNeighbourX(Alloc& a,const Point& p, Node*& best, double& max, int depth);
    virtual void findInSphereX(Alloc& a,const Point& p ,double radius, NodeList& result, int depth) ;
    virtual void kNearestNeighboursX(Alloc& a,const Point& p ,size_t k, NodeQueue& result, int depth) ;

    //==========================

    template<typename Container>
    static double distanceToPlane(const Container& in, const HyperPlane& plane);

};

} // end namespace

#include "BSPNode.cc"

#endif
