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

    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
    Mixed sequences of polygons and triangles. 

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

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

#ifndef MixedPolyhedron_H
#define MixedPolyhedron_H

#include <memory>
#include "tag.H"

#include <list>
#include <deque>
#include <vector>

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

namespace Foam { namespace GeometricalTransport { 

/*---------------------------------------------------------------------------*\
                         Class MixedPolyhedron Declaration
\*---------------------------------------------------------------------------*/

template
<
    typename Triangle, 
    typename Polygon,    
    template<typename, typename> class SequenceContainer,
    template <typename T> class Allocator = std::allocator
>
class MixedPolyhedron
{
    public: 

    typedef Polygon PolygonType;
    typedef Triangle TriangleType;
    typedef SequenceContainer<Triangle, Allocator<Triangle>> TrianglesType;
    typedef SequenceContainer<Polygon, Allocator<Polygon>> PolygonsType;
    typedef typename Triangle::value_type PointType; 

    private: 

    TrianglesType triangles_; 
    PolygonsType polygons_; 

    public: 

        auto triangles_begin() 
        {
            return triangles_.begin(); 
        }

        auto triangles_begin()  const
        {
            return triangles_.begin(); 
        }

        auto triangles_end() 
        {
            return triangles_.end(); 
        }

        auto triangles_end()  const
        {
            return triangles_.end(); 
        }

        auto polygons_begin() 
        {
            return polygons_.begin(); 
        }

        auto polygons_begin()  const
        {
            return polygons_.begin(); 
        }

        auto polygons_end() 
        {
            return polygons_.end(); 
        }

        auto polygons_end()  const
        {
            return polygons_.end(); 
        }

        void push_back(Triangle const & triangle)
        {
            triangles_.push_back(triangle); 
        }

        void push_back(Polygon const & polygon)
        {
            polygons_.push_back(polygon); 
        }

        const auto& polygons() const
        {
            return polygons_; 
        }

        auto& polygons() 
        {
            return polygons_; 
        }

        const auto& triangles() const
        {
            return triangles_; 
        }

        auto& triangles() 
        {
            return triangles_; 
        }

        auto triangles_size() const
        {
            return triangles_.size();
        }

        decltype(auto) triangles_front() const
        {
            return triangles_.front();
        }

        decltype(auto) triangles_back() const
        {
            return triangles_.back();
        }

        auto polygons_size() const
        {
            return polygons_.size();
        }

        decltype(auto) polygons_front() const
        {
            return polygons_.front();
        }

        decltype(auto) polygons_back() const
        {
            return polygons_.back();
        }

        auto size() const
        {
            return triangles_size() + polygons_size(); 
        }
};

namespace Traits {

    template
    <
        typename Triangle, 
        typename Polygon,    
        template<typename, typename> class Sequence,
        template <typename T> class Allocator 
    >
    struct tag 
    <
        MixedPolyhedron<Triangle, Polygon, Sequence, Allocator>
    >
    {
        typedef mixed_polyhedron_tag type;
    };

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

} // end namespace Geometry::Traits 

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

}} // end namespace Foam::GeometricalTransport

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

#endif

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