/*
 * (C) Copyright 1996-2012 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

/// @author Piotr Kuchta
/// @date April 2009
/// @author Simon Smart
/// @date January 2019

#ifndef odc_core_Header_H
#define odc_core_Header_H

#include <cstddef>
#include <cstdint>
#include <map>
#include <string>
#include <vector>

#include "eckit/io/Buffer.h"

namespace eckit {
class DataHandle;
}


namespace odc {
namespace core {

class MetaData;
using Properties = std::map<std::string, std::string>;
using Flags      = std::vector<double>;

//----------------------------------------------------------------------------------------------------------------------

const int32_t BYTE_ORDER_INDICATOR = 1;
const uint16_t ODA_MAGIC_NUMBER    = 0xffff;

const int32_t FORMAT_VERSION_NUMBER_MAJOR = 0;
const int32_t FORMAT_VERSION_NUMBER_MINOR = 5;

//----------------------------------------------------------------------------------------------------------------------

class Header {

public:  // methods

    Header(MetaData& md, Properties& props);

    Header(const Header&)            = delete;
    Header& operator=(const Header&) = delete;

    ~Header();

    size_t dataSize() const { return dataSize_; }

    size_t rowsNumber() const { return rowsNumber_; }

    int32_t byteOrder() { return byteOrder_; }

    /// read Magic loads the MAGIC from the data handle. Returns 0 for end of stream,
    /// and throws an exception if the magic is incorrect.
    static bool readMagic(eckit::DataHandle& dh);

    void loadAfterMagic(eckit::DataHandle& dh);

    static std::pair<eckit::Buffer, size_t> serializeHeader(size_t dataSize, size_t rowsNumber,
                                                            const Properties& properties, const MetaData& columns);

    static std::pair<eckit::Buffer, size_t> serializeHeaderOtherByteOrder(size_t dataSize, size_t rowsNumber,
                                                                          const Properties& properties,
                                                                          const MetaData& columns);

private:  // members

    template <typename ByteOrder>
    void load(eckit::DataHandle& dh);

    MetaData& md_;
    Properties& props_;
    size_t dataSize_;
    size_t rowsNumber_;

    int32_t byteOrder_;
};

//----------------------------------------------------------------------------------------------------------------------

}  // namespace core
}  // namespace odc


#endif  // odc_core_Header_H
