/***************************** 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 *************************************/

#pragma once

#include <cassert>

#include <iostream>
#include <map>
#include <vector>
#include <list>
#include <set>

#ifdef METVIEW
#include <Metview.h>
#endif

#include "MvMessageMetaData.h"

#include "eccodes.h"

class BufrFilterDef;
class BufrLocationCollector;
class MvKeyProfile;
class MvKey;
class MvEccBufrMessage;

class BufrDataDump
{
public:
    BufrDataDump() = default;
    ~BufrDataDump();
    void clear();
    bool read(const std::string&, int, int, int, bool, long, std::string&);
    bool debug(const std::string&, int, int, int, bool, long, std::string&);
    const std::string& text() const { return text_; }
    const std::string& debug() const { return debug_; }
    const std::string& debugInfo() const { return debugInfo_; }

    bool runMessageFilter(const std::string& filterStr, const std::string& fileName,
                          const std::string& resFile);

protected:
    bool filterMessage(const std::string& inFile, int msgCnt, long offset, const std::string& outFile, std::string&);
    bool filterSubset(const std::string& inFile, int msgCnt, int subsetCnt, const std::string& outFile, std::string&);

    std::string dumpFile_;
    std::string text_;
    std::string debug_;
    std::string debugInfo_;
};

class BufrExpandDataDump
{
public:
    BufrExpandDataDump() = default;
    ~BufrExpandDataDump();
    void clear();
    bool read(const std::string&, int, long, std::string&);
    const std::string& text() const { return text_; }

private:
    std::string dumpFile_;
    std::string text_;
};

class BufrMetaData : public MvMessageMetaData
{
public:
    BufrMetaData();
    BufrMetaData(const std::string& fileName, int totalMessageNum);

    ~BufrMetaData() override;
    void setFileName(std::string) override;

    void getKeyList(std::string, MvKeyProfile*);

    void setTotalMessageNum(int) override;
    size_t totalSubsetNum(bool forceCompute);
    void setMessage(size_t chunkStart, const std::vector<MvEccBufrMessage*>& msgVec);
    void setMessage(size_t pos, MvEccBufrMessage* msg);
    std::vector<MvEccBufrMessage*> messages() const { return messages_; }
    MvEccBufrMessage* message(int) const;

    void readCompressedData(MvKeyProfile* prof, int index, int subsetNum);
    bool readLocations(BufrLocationCollector* collector, std::string& errOut);
    const std::string& firstTypicalDate() const { return firstTypicalDate_; }
    const std::set<std::string>& firstMessageKeys();
    void readMessageKeys(int index, std::set<std::string>&);
    void getKeyProfileForFirstMessage(MvKeyProfile* prof);
    int computeTotalMessageNum();
    void clearData() override;

protected:
    void clear() override;

private:
    void allocateMessages();
    void readMessage(MvKeyProfile* prof, codes_handle* ch);
    void readCompressedData(MvKeyProfile* prof, codes_handle* ch);
    void readMessageLocations(codes_handle* ch, int msgCnt, BufrLocationCollector* collector);
    void readDoubleArray(codes_handle* ch, const std::string& key, std::size_t len, std::size_t& allocLen, double** data);
    std::string formatDate(std::string, std::string, std::string);
    std::string formatTime(std::string, std::string, std::string);
    static void checkStringValue(std::string&);

    std::string tmpFile_;
    MvKeyProfile* allKey_{nullptr};
    std::vector<MvEccBufrMessage*> messages_;
    std::string firstTypicalDate_;
    std::set<std::string> firstKeys_;
    size_t totalSubsetNum_{0};
};
