#ifndef INCLUDED_AGEGROUPVSD_
#define INCLUDED_AGEGROUPVSD_

#include <iosfwd>
#include "../agegroup/agegroup.h"
#include "../vsd/vsd.h"

class AgeGroupVSD
{
    friend std::istream &operator>>(std::istream &in, AgeGroupVSD &group);
    friend std::ostream &operator<<(std::ostream &out, 
                                    std::vector<AgeGroupVSD> const &vect);
    friend std::ostream &operator<<(std::ostream &out, 
                                                AgeGroupVSD const &group);
    AgeGroup d_ageGroup;

    VSD      d_vsd;
    double   d_stdDev;      // if negative: std dev not used

    static unsigned s_indent;

    public:
        AgeGroupVSD(VaryType varyType, bool useStdDev);

        AgeGroup const &ageGroup() const;

        uint16_t beginAge() const;
        uint16_t endAge() const;

        double value() const;
        double stdDev() const;

        void vary();

        static void fmt(unsigned valueIntWidth, unsigned valuePrec,     // inl
                        unsigned distValueWdith, unsigned distPrec);
        
        static void fmt(unsigned indent,    // indentation below topLabel
                        unsigned mIntWidth, unsigned mPrec, 
                        unsigned sdIntWidth, unsigned sdPrec);

        static void vary(std::ostream &out, unsigned indent,            // 2
                        char const *hdr, std::vector<AgeGroupVSD> &vect);

    private:
        std::ostream &insert(std::ostream &out) const;                    // 1

        static std::ostream &insert(std::ostream &out,                    // 2
                                    std::vector<AgeGroupVSD> const &vect);

        std::istream &extract(std::istream &in);
};

typedef std::vector<AgeGroupVSD> AgeGroupVSDvect;

inline AgeGroup const &AgeGroupVSD::ageGroup() const
{
    return d_ageGroup;
}

inline uint16_t AgeGroupVSD::beginAge() const
{
    return d_ageGroup.beginAge();
}

inline uint16_t AgeGroupVSD::endAge() const
{
    return d_ageGroup.endAge();
}

inline double AgeGroupVSD::value() const
{
    return d_vsd.value();
}

inline double AgeGroupVSD::stdDev() const
{
    return d_stdDev;
}

// static
inline void fmt(unsigned valueIntWidth, unsigned valuePrec,    
                unsigned distValueWdith, unsigned distPrec)
{
    VSD::fmt(valueIntWidth, valuePrec, distValueWdith, distPrec);
}

inline std::istream &operator>>(std::istream &in, AgeGroupVSD &ageGroupVSD)
{
    return ageGroupVSD.extract(in);
}

inline std::ostream &operator<<(std::ostream &out, 
                                            AgeGroupVSD const &ageGroupVSD)
{
    return ageGroupVSD.insert(out);
}

inline std::ostream &operator<<(std::ostream &out, 
                                AgeGroupVSDvect const &vect)
{
    return AgeGroupVSD::insert(out, vect);
}

#endif


