/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#ifndef MvFlextra_inc
#define MvFlextra_inc

#include <fstream>
#include <map>
#include <string>
#include <vector>

using namespace std;

class MvFlextraBlock;

class MvFlextraItem
{
    friend class MvFlextraBlock;

public:
    enum DataType
    {
        NoType,
        DateType,
        IntType,
        FloatType
    };

    MvFlextraItem(int);
    string metaData(const string&) const;
    const map<string, string>& metaData() const { return metaData_; }
    void pointData(const string&, vector<string>&, DataType&) const;
    void addMetaData(const string& key, const string& value) { metaData_[key] = value; }
    void addPoint(const vector<string>& pt) { points_.push_back(pt); }
    const vector<vector<string> >& points() const { return points_; }
    int id() const { return id_; }

protected:
    map<string, int> pointKeyIndex_;
    map<string, DataType> pointKeyType_;
    int id_;
    map<string, string> metaData_;
    vector<vector<string> > points_;
};


class MvFlextra;

class MvFlextraBlock
{
    friend class MvFlextra;

public:
    MvFlextraBlock();
    ~MvFlextraBlock();

    const string& comment() const { return comment_; }
    void writeAll(const string&, int&);
    void writeHighlightPoints(const string&, int&, string);
    void writeLabels(const string&, int&, string, vector<string>&);
    int itemNum() const { return static_cast<int>(items_.size()); }
    const map<string, string>& metaData() const { return metaData_; }
    const vector<MvFlextraItem*>& items() const { return items_; }
    bool constantStep() const { return constantStep_; }
    void setUncertantyTr(bool b) { uncertaintyTr_ = b; }
    bool uncertaintyTr() const { return uncertaintyTr_; }

protected:
    void decode(string);
    void decode(ifstream& in, string& line);
    void writeMetaData(ofstream&, int&);
    bool parseHeaderLine(const string& line, const string& key, string& value);
    bool parseHeaderLine(const string& line, const string& key, string& fromValue, string& toValue);
    bool isMetaDataConst(const string& key);
    void checkStepType();

    //string fileName_;
    string comment_;
    string direction_;
    map<string, string> metaData_;
    vector<MvFlextraItem*> items_;
    bool constantStep_;
    bool uncertaintyTr_;
};

class MvFlextra
{
public:
    MvFlextra(const string&);
    ~MvFlextra();

    const string& fileName() const { return fileName_; }
    int blockNum() const { return static_cast<int>(blocks_.size()); }
    const vector<MvFlextraBlock*>& blocks() const { return blocks_; }
    void write(FILE* f);
    void write(const string&, int);


protected:
    void decode();

    string fileName_;
    vector<MvFlextraBlock*> blocks_;
};


#endif
