/***************************** 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 <string>
#include <vector>

#ifdef METVIEW
// For off_t
#include "mars.h"
#else
#include <sys/types.h>
#endif

class MvKeyProfile;
class MvMessageMetaDataObserver;

class MvMessageMetaData
{
public:
    enum Type
    {
        GribType,
        BufrType,
        Notype
    };

    MvMessageMetaData(Type type) :
        type_(type),
        messageNum_(0),
        totalMessageNum_(0),
        firstScan_(true),
        filterEnabled_(false) {}
    virtual ~MvMessageMetaData() = default;

    Type type() const { return type_; }
    const std::string& fileName() const { return fileName_; }
    virtual void setFileName(std::string) = 0;
    int messageNum() { return messageNum_; }
    int totalMessageNum() { return totalMessageNum_; }
    virtual void setTotalMessageNum(int) = 0;

    void registerObserver(MvMessageMetaDataObserver* obs);
    virtual bool useMessageSizeForProgressIndicator() { return false; }
    bool isFilterEnabled() { return filterEnabled_; }
    virtual void setFilter(const std::vector<off_t>&, const std::vector<int>&) {}
    virtual void updateFilterCnt(const std::vector<off_t>& /*offset*/, const std::vector<int>& /*cnt*/) {}
    int unfilteredMessageCnt(int cntStartFromZero) const
    {
        return (filterEnabled_) ? (filterCnt_[cntStartFromZero]) : cntStartFromZero + 1;
    }

    bool firstScan() const { return firstScan_; }
    void setFirstScan(bool b) { firstScan_ = b; }

    const std::vector<off_t>& filterOffset() const { return filterOffset_; }
    const std::vector<int>& filterLen() const { return filterLen_; }
    const std::vector<int>& filterCnt() const { return filterCnt_; }

    virtual void clearData()
    {
        messageNum_ = 0;
        totalMessageNum_ = 0;
        firstScan_ = true,
        filterEnabled_ = false,
        filterOffset_.clear();
        filterLen_.clear();
        filterCnt_.clear();
    }

protected:
    using IntMethod = void (MvMessageMetaDataObserver::*)(int);

    using VoidMethod = void (MvMessageMetaDataObserver::*)();
    void broadcast(IntMethod, int);
    void broadcast(VoidMethod);

    virtual void clear()
    {
        fileName_.clear();
        messageNum_ = 0;
        totalMessageNum_ = 0;
        firstScan_ = true,
        filterEnabled_ = false,
        filterOffset_.clear();
        filterLen_.clear();
        filterCnt_.clear();
    }

    Type type_;
    std::string fileName_;
    int messageNum_;
    int totalMessageNum_;
    bool firstScan_;
    bool filterEnabled_;
    std::vector<off_t> filterOffset_;
    std::vector<int> filterLen_;
    std::vector<int> filterCnt_;

    std::vector<MvMessageMetaDataObserver*> observers_;
};


class MvMessageMetaDataObserver
{
public:
    MvMessageMetaDataObserver() = default;
    virtual ~MvMessageMetaDataObserver() = default;

    virtual void messageScanStepChanged(int) {}
    virtual void locationScanStepChanged(int) {}
    virtual void messageFilterStarted() {}
    virtual void messageFilterFinished() {}
};
