#ifndef TN_MAP_ANNOTATION_PARAMS_H
#define TN_MAP_ANNOTATION_PARAMS_H

#include "TnMapStyleParams.h"

#include <string>

#include <foundation/SharedPtr.h>
#include <foundation/TnTypes.h>
#include <foundation/Math/Vec.hpp>
#include <foundation/Math/Matrix.hpp>

#include "TnMapAnnotationType.h"
#include "TnMapLayer.h"
#include "TnMapProjectionStyle.h"


// Forward declarations, never include engine internals in public files
class  TnMapConf;
class  TnMapGroupIconParams;

/*  NOTE:
    Refrain from putting anything other than smart pointers or concrete
    types in this class.  This will prevent the need for writing copy 
    constructors
 */

class TnMapAnnotationParams : public TnMapStyleParams
{
public:
    
    friend class TnMapStyleParamsFactory;
    
    // Accessors/Setters
    
    //super group shared pointer
    Tn::Foundation::shared_ptr<TnMapGroupIconParams> const & SuperGroupPtr() const;
    
    // Old API params
    double GetLatitudeDegrees() const;
    double GetLongitudeDegrees() const;
    double GetHeightMeters() const;
    
    TnMapAnnotationParams & SetLatitudeLongitude(double latitudeDegrees, double longitudeDegrees);
    TnMapAnnotationParams & SetLatitudeLongitudeHeight(double latitudeDegrees, double longitudeDegrees, double heightMeters);
    
    std::string const &         GetText() const;
    TnMapAnnotationParams &     SetText(std::string const & text);
    
    eTnMapLayer                 GetAnnotationLayer() const;
    TnMapAnnotationParams &     SetAnnotationLayer(eTnMapLayer layer);
    
    double                      GetPriorityBias() const;
    TnMapAnnotationParams &     SetPriorityBias(double priorityBias);
    
    double                      GetRotation() const;
    TnMapAnnotationParams &     SetRotation(double rotation);
    
    bool                        GetRotateFlag() const;
    TnMapAnnotationParams &     SetRotateFlag(bool flag);
    
    //Exposed config
    std::string const &         GetStyle() const;
    TnMapAnnotationParams &     SetStyle(std::string const & style);

    std::string const &         GetCullImmunityGroupName() const;
    TnMapAnnotationParams &     SetCullImmunityGroupName(std::string const & style);

    std::string const &         GetIconName() const;
    TnMapAnnotationParams &     SetIconName(std::string const & iconName);

    //icon text offset
    int                         GetTextX() const;
    TnMapAnnotationParams &     SetTextX(int text_x);
    int                         GetTextY() const;
    TnMapAnnotationParams &     SetTextY(int text_y);
    
    //icon offset
    int                         GetIconX() const;
    TnMapAnnotationParams &     SetIconX(int icon_x);
    int                         GetIconY() const;
    TnMapAnnotationParams &     SetIconY(int icon_y);
    
    //icon dimensions
    int                         GetIconWidth() const;
    TnMapAnnotationParams &     SetIconWidth(int icon_w);
    int                         GetIconHeight() const;
    TnMapAnnotationParams &     SetIconHeight(int icon_h);
    
    //icon texture coordinates
    double                      GetTexCoordLeft() const;
    TnMapAnnotationParams &     SetTexCoordLeft(double texcoord_left);
    double                      GetTexCoordRight() const;
    TnMapAnnotationParams &     SetTexCoordRight(double texcoord_right);
    double                      GetTexCoordBottom() const;
    TnMapAnnotationParams &     SetTexCoordBottom(double texcoord_bottom);
    double                      GetTexCoordTop() const;
    TnMapAnnotationParams &     SetTexCoordTop(double texcoord_top);
    
    TnMapAnnotationParams &     SetAnimationTime(double animation_time);
    double                      GetAnimationTime() const;
    
    TnMapAnnotationParams &     SetAnimationType(eAnnotationTransitionType type);
    eAnnotationTransitionType   GetAnimationType() const;
    
    TnMapAnnotationParams &     SetTextColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 0);
    uint8_t                     GetTextColorRed()   const;
    uint8_t                     GetTextColorGreen() const;
    uint8_t                     GetTextColorBlue()  const;
    uint8_t                     GetTextColorAlpha() const;
    
    TnMapAnnotationParams &     SetOutlineColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 0);
    uint8_t                     GetOutlineColorRed()   const;
    uint8_t                     GetOutlineColorGreen() const;
    uint8_t                     GetOutlineColorBlue()  const;
    uint8_t                     GetOutlineColorAlpha() const;
    
    TnMapAnnotationParams &     SetAnnotationType(eTnMapAnnotationType type);
    eTnMapAnnotationType        GetAnnotationType() const;
    
    void                        SetRenderSize(float renderSize);
    float                       GetRenderSize() const;
    
    void                        SetCullDistance(double cullDistance);
    double                      GetCullDistance() const;
    
    void                        SetAlwaysVisible(bool alwaysVisible);
    bool                        AlwaysVisible() const;
    
    // Getters for the rest

    /*  If ignore is set to true, don't even bother building it. */
    bool                        Ignore() const;
    void                        SetIgnore(bool);
    
    double                      GetPriority() const;
    double                      GetBiasedPriority() const;
    std::string const &         GetFontFace() const;
    eTnMapFontStyle             GetFontFaceStyle() const;
    int                         GetFontSize() const;
    int                         GetFontHaloSize() const;
    eTextAlignment              GetTextAlignment() const;
    std::string const &         GetSuperGroup() const;

    void ShowInMapProjection(eTnMapProjectionStyle projectionStyle);
    eTnMapProjectionStyle ShowInMapProjection() const;

    bool                        TextureAtlased() const;
    
    //Special setters for Fixed Annotation Rotation Matrix
    void    SetFixedAnnotationRotationMatrix(Tn::math::Vec3f const & faceVector,
                                             Tn::math::Vec3f const & upVector);
    void    SetFixedAnnotationRotationMatrix(Tn::Foundation::shared_ptr<Tn::math::Matrixf> const & rotationMatrix);
    
    Tn::Foundation::shared_ptr<Tn::math::Matrixf> const & GetFixedAnnotationRotationMatrix() const;

    void                        SetAlphaEffectValue(double alphaEffectValue);
    double                      GetAlphaEffectValue() const;
    void                        SetTextOverallSpace(double overallSpace);
    double                      GetTextOverallSpace() const;
public:
    
    //Factory responsible for construction
    TnMapAnnotationParams(Tn::Foundation::shared_ptr<TnMapConf> const & conf,
                          std::string const & styleKey,
                          uint32_t zoomLevel);
    
private:
    
    //Read values from config based on StyleKey
    void ReadStyle();

    //Construct the SuperGroupParmams::ptr
    void BuildSuperGroupParams();
    
    //super group ptr, privately built
    Tn::Foundation::shared_ptr<TnMapGroupIconParams> super_group_ptr;
    
    //typical api values

    // cull immunity group name
    std::string immunity_group;

    //positional
    double degreesLatitude, degreesLongitude, metersHeight;
    //text to display
    std::string text;
    //layer info
    eTnMapLayer layer;
    //priority bias
    double priorityBias;
    
    //optional rotation value, inited to 0.0
    double rotation;
    
    bool rotateFlag;
    
    
    // config values, only those deemed worthy will be exposed!
    std::string style;
    std::string icon_name;
    
    double      priority;
    int         text_x, text_y;
    int         icon_x, icon_y;
    int         icon_w, icon_h;
    
    std::string font_face;
    eTnMapFontStyle    font_faceStyle;
    
    int         font_size;
    int         font_halo_size;
    
    float       render_size;
    
    uint8_t     textColorRed, textColorBlue, textColorGreen, textColorAlpha;
    uint8_t     outlineColorRed, outlineColorBlue, outlineColorGreen, outlineColorAlpha;
    
    eTextAlignment text_alignment;
    std::string    super_group;
    
    bool        always_visible;
    eTnMapProjectionStyle    showInMapProjection;

    double      texcoord_left, texcoord_bottom, texcoord_right, texcoord_top;
    
    double      animation_time;
    
    eAnnotationTransitionType animation_type;
    
    double      cull_distance; //a negative cull distance indicates infinite distance

    double      alpha_effect_value;
    
    eTnMapAnnotationType annotationType;
    
    //Only for fixed annotations
    Tn::Foundation::shared_ptr<Tn::math::Matrixf> m_fixedAnnotationMatrix; 

    double      text_overall_space;
    
    bool        ignore;
    
};

#endif

/*  Default Style json structure for reference
 
"style" : "billboard_icon",
"icon_name" : "missing_traffic.png",
"priority" : 20,
"text_x" : 0,
"text_y" : 20,
"icon_x" : 20,
"icon_y" : 0,
"icon_w" : 40,
"icon_h" : 40,
"font_face" : "Arial",
"font_size" : 26,
"render_size" : 14,
"text_color" : "#000000ff",
"outline_color" : "#ffffff7f",
"text_alignment" : "center",
"super_group" : "traffic_annotation_group",
"always_visible" : false,
"show_in_2d" : true,
"texcoord_left" : 0.0,
"texcoord_bottom" : 0.0,
"texcoord_right" : 1.0,
"texcoord_top" : 1.0
 
*/
