#ifndef __TN_BING_TILE_PROVIDER_H__
#define __TN_BING_TILE_PROVIDER_H__

#include <map>
#include <string>
#include <vector>
#include "foundation/TnTypes.h"
#include "foundation/Thread.h"
#include "foundation/Mutex.h"
#include "TnTileProvider.h"

class TnBingTileProvider : public TnTileProvider
{
public:
    TnBingTileProvider(std::string const & apiKey,
                       TnMapRasterTileData::eProviderType type);
    
    virtual ~TnBingTileProvider();

    // Fill in RasterTileImageData, and set the request result
    virtual void GetTilesFor(TnMapRasterTileData::ptr const & data, int zoomBias);// The more negative, the more blurry.    
                                                                                    // Default in json should be -1
    
private:
    
    //Get imagery set associated with provider type
    std::string ImagerySet(TnMapRasterTileData::eProviderType type) const;
    
    // Add a Bing tile to the request returning 1 if a tile was added
    int AddTile(std::string const & quadkey, TnMapRasterTileData::ptr const & data);
    
    // Build a URL for an image at the given quadkey (or look up in cache)
    int UrlForQuadkey(std::string const & quadkey, std::string & url);
        
    // Convert between pixel XY and lat/lon    
    int LatLonToPixelXY(double latitude, double longitude, int lod, int & pixelX, int & pixelY);
    int PixelXYToLatLon(int pixelX, int pixelY, int lod, double & latitude, double & longitude);
    
    // Convert between tile XY and pixel XY
    int PixelXYToTileXY(int pixelX, int pixelY, int & tileX, int & tileY);
    int TileXYToPixelXY(int tileX, int tileY, int & pixelX, int & pixelY);
    
    // Convert between quadkey and tile XY
    int TileXYToQuadkey(int tileX, int tileY, int lod, std::string & quadkey);
    int QuadkeyToTileXY(std::string const & quadkey, int & tileX, int & tileY, int & lod);
    
private:
    // Background loader for metadata URL
    void BackgroundLoader(std::string const & apikey, std::string const & imagerySet);

    // <ImageUrl> from Microsoft
    std::string m_ImageUrl;
    
    // API key for Microsoft
    std::string m_APIKey;
    
    // <ImageUrlSubdomains> from Microsoft
    std::vector<std::string> m_ImageUrlSubdomains;
    
    // <ImageWidth> from Microsoft
    int m_ImageWidth;

    // <ImageHeight> from Microsoft
    int m_ImageHeight;
    
    // <ZoomMin> from Microsoft
    int m_ZoomMin;

    // <ZoomMax> from Microsoft
    int m_ZoomMax;
    
    // tag locations
    size_t m_SubdomainTag;
    size_t m_QuadkeyTag;
    size_t m_CultureTag;
    size_t m_TokenTag;

    // Indication that current image url has been loaded
    bool m_CurrentUrl;
    
    // Cache our mapping between quadkey and url
    std::map<std::string,std::string> m_Cache;

    // Threaded bing contact
    Tn::Foundation::shared_ptr<Tn::Foundation::thread> m_Thread;
    Tn::Foundation::mutex m_Mutex;
};

#endif

