//
//  TiledMapLayer.hpp
//  Meteor
//
//  Created by Cesar Parent on 10/09/2015.
//  Copyright © 2015 Cesar Parent. All rights reserved.
//

#ifndef TiledMapLayer_hpp
#define TiledMapLayer_hpp

#include "../Nodes/Layer.h"
#include "TiledMapInfo.h"
#include <vector>
#include <string>

namespace tinyxml2 {
    class XMLElement;
}

NS_BEGIN


class Tile;

/*!
 * @class           TiledMapLayer
 * @ingroup         tiledmap
 * @brief           A layer node that stores and display a tiledmap's layer.
 * @details         A tiled map layer stores an array of all its tiles, and provides an API to
 *                  access tiles based on their coordinates, or a 2D position.
 * @note            You should not create a tiled map layer directly. Instead, you should load a
 *                  TMX file though TiledMap::TiledMap(const std::string&) and request layers by
 *                  name using TiledMap::layerNamed(const std::string&).
 */
class TiledMapLayer : public Layer {
public:
    
    /*!
     * @internal
     * @brief       Creates a Tiled Map Layer from a chunck of XML data.
     * @param       data        XML node containing the data needed to constuct the layer.
     * @param       info        Tiled Map's common information.
     */
    TiledMapLayer(const tinyxml2::XMLElement* data, const TiledMapInfo& info);
    
    /*!
     * @internal
     * @brief       Default destructor.
     */
    virtual ~TiledMapLayer() {}
    
    /**
     * @name        Inspecting A TiledMapLayer's Tiles
     * @{
     */

    /*!
     * @brief       Returns the Tile ID of a tile.
     * @param       path        The tile's coordinates in the layer.
     * @return      The GID of the tile at `path`, or 0 if there is no tile for that path.
     */
    Uint32
    tileGIDForIndexPath(const ivec2& path) const;
    
    /*!
     * @brief       Returns the bounds of a tile.
     * @param       path        The tile's coordinates in the layer.
     * @return      The bounds of the tile at `path`, or Rect::nullRect if there is no tile for that
     *              path.
     */
    Rect
    tileBoundsForIndexPath(const ivec2& path) const;
    
    /*!
     * @brief       Returns the tile at the given coordinates.
     * @param       path        The tile's coordinates in the layer.
     * @param       The tile at `path`, or `ARC<nullptr>` if there is no tile for that path.
     */
    ARC<Tile>
    tileAtIndexPath(const ivec2& path) const;
    
    /*!
     * @brief       Returns the first tile with a given GID.
     * @param       gid         The tile's identifier.
     * @return      The first tile with the given GID, or nil if no tile was found.
     */
    ARC<Tile>
    firstTileWithGID(Uint32 gid) const;
    
    /**
     * @}
     */
    
private:
    
    long unsigned int
    indexForIndexPath(const ivec2& path) const {
        return (path.y * _info.mapSize.width) + path.x;
    }
    
    /*!
     * @brief       Reference to the tiled map's information.
     */
    const TiledMapInfo& _info;
    
    std::vector<ARC<Tile>> _tiles;
};


NS_END


#endif /* TiledMapLayer_hpp */
