/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2014 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_DRIVERS_REX_MASK_GENERATOR
#define OSGEARTH_DRIVERS_REX_MASK_GENERATOR 1

#include "Common"
#include <osgEarth/MapFrame>
#include <osgEarth/TileKey>
#include <osg/Geometry>

#define MASK_MARKER_DISCARD  0.0f    // do not draw
#define MASK_MARKER_NORMAL   1.0f    // normal vertex
#define MASK_MARKER_SKIRT    2.0f    // not subject to morphing
#define MASK_MARKER_BOUNDARY 3.0f    // not subject to elevation texture

namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
{
    using namespace osgEarth;

    /**
     * Record that stores the data for a single masking region.
     */
    struct MaskRecord
    {
        osg::ref_ptr<osg::Vec3dArray> _boundary;
        osg::Vec3d                    _ndcMin, _ndcMax;
        osg::Geometry*                _geom;
        osg::ref_ptr<osg::Vec3Array>  _internal;

        MaskRecord(osg::Vec3dArray* boundary, osg::Vec3d& ndcMin, osg::Vec3d& ndcMax, osg::Geometry* geom) 
            : _boundary(boundary), _ndcMin(ndcMin), _ndcMax(ndcMax), _geom(geom), _internal(new osg::Vec3Array()) { }
    };

    typedef std::vector<MaskRecord> MaskRecordVector;


    /**
     * Creates geometry for the part of a tile containing mask data.
     */
    class MaskGenerator : public osg::Referenced
    {
    public:
        MaskGenerator(const TileKey& key, unsigned tileSize, const MapFrame& mapFrame);


        bool hasMasks() const
        {
            return _maskRecords.size() > 0;
        }

        /** whether a texcoord indicates that the corresponding vert is masked. */
        bool isMasked(const osg::Vec3f& texCoord) const
        {
            return texCoord.z() == MASK_MARKER_DISCARD;
        }

        /** whether the masking geometry contains a unit location. */
        /*  0.0 - contains                                         */
        /*  1.0 - does not contain                                 */
        /*  2.0 - does not contain but is a tile vert on the outer */
        /*        masking skirt boundary                           */
        float getMarker(float nx, float ny) const;

        bool containedByQuadAtColRow(int col, int row, int tileSize) const
        {
            // Placeholder for now.
            return false;
        }

        void getMinMax(osg::Vec3d& min, osg::Vec3d& max);

        osg::DrawElementsUInt* createMaskPrimitives(const MapInfo& mapInfo, osg::Vec3Array* verts, osg::Vec3Array* texCoords,  osg::Vec3Array* normals, osg::Vec3Array* neighbors);

    protected:
        void setupMaskRecord(const MapFrame& mapFrame, osg::Vec3dArray* boundary);

    protected:
        const TileKey    _key;
        unsigned _tileSize;
        MaskRecordVector _maskRecords;
        osg::Vec3d _ndcMin, _ndcMax;
    };

} } } // namespace osgEarth::Drivers::RexTerrainEngine

#endif // OSGEARTH_DRIVERS_REX_MASK_GENERATOR
