/*---------------------------------------------------------------------------*\

    geophase: A C++ template library for geometrical operations on non-convex
    polyhedra with non-planar faces
     
    Copyright (C) 2019 Tomislav Maric, TU Darmstadt 

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.


Description
    Halfspace class.  

Author
    Tomislav Maric maric@mma.tu-darmstadt.de

\*---------------------------------------------------------------------------*/

#ifndef Halfspace_HPP
#define Halfspace_HPP

#include "tag.hpp"
#include "Vector.hpp"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace geophase {

/*---------------------------------------------------------------------------*\
                         Class Halfspace Declaration
\*---------------------------------------------------------------------------*/

template<typename Vector, typename Enabled=void> 
class Halfspace; 

template<typename Vector> 
class Halfspace<Vector, enable_if_type_tagged_t<Vector, vector_tag>> 
{
    Vector position_; 
    Vector direction_; 

public:

    using value_type = Vector; 

    Halfspace() = default; 

    Halfspace(
        Vector const& position, 
        Vector const& direction
    )
    : 
        position_(position), 
        direction_(direction)
    {}

    Vector const& direction() const
    {
        return direction_; 
    }

    Vector& direction() 
    {
        return direction_; 
    }

    Vector& n() 
    {
        return direction_; 
    }

    Vector const& n() const
    {
        return direction_; 
    }

    Vector const& orientation() const
    {
        return direction_;  
    }

    Vector& orientation() 
    {
        return direction_;  
    }

    Vector const& position() const
    {
        return position_;
    }
    
    Vector& position() 
    {
        return position_;
    }

    Vector& p() 
    {
        return position_;
    }

    Vector const& p() const
    {
        return position_;
    }

    template<typename VectorType>
    void setDirection(VectorType&& direction) 
    {
        direction_ = direction;  
    }

    template<typename VectorType>
    void setOrientation(VectorType&& direction) 
    {
        setDirection(direction); 
    }
  
    template<typename PointType>
    void setPosition(PointType const & n) 
    {
        position_ = n;
    }

    void flip() 
    {
        direction_ *= -1; 
    }

    template<typename Pair>
    void operator=(Pair const& p)
    {
        position_ = p.first; 
        direction_ = p.second; 
    }
};

template<typename Vector> 
struct tag<Halfspace<Vector>>
{
    using type = halfspace_tag;
};


template<typename Halfspace>
std::enable_if_t<type_tagged<Halfspace, halfspace_tag>(), bool> // Shorten. TM. 
operator==(Halfspace const& h1, Halfspace const& h2)
{
    return (h1.position() == h2.position()) && (h1.direction() == h2.direction()); 
}

// Common halfspaces.
using halfspace = Halfspace<vector>; 

} // End namespace geophase 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
