/*
 * (C) Copyright 2013 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.
 */

#pragma once

#include <cassert>
#include <vector>

#include "atlas/library/config.h"
#include "atlas/util/Config.h"

namespace atlas {

class Field;

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

class Vertical {
public:
    template <typename vector_t>  // expect "vector_t::size()" and "vector_t::operator[]"
    Vertical(idx_t levels, const vector_t& z, const util::Config& config = util::NoConfig());

    template <typename vector_t, typename Interval>  // expect "vector_t::size()" and "vector_t::operator[]"
    Vertical(idx_t levels, const vector_t& z, const Interval& interval, const util::Config& config = util::NoConfig());

    Vertical(const util::Config& config = util::NoConfig());

    Field z() const;

public:
    idx_t k_begin() const { return k_begin_; }
    idx_t k_end() const { return k_end_; }
    idx_t size() const { return size_; }

    template <typename Int>
    double operator()(const Int k) const {
        return z_[k];
    }

    template <typename Int>
    double operator[](const Int k) const {
        return z_[k];
    }

    double min() const { return min_; }
    double max() const { return max_; }

    double front() const { return z_.front(); }
    double back() const { return z_.back(); }

    /// @brief Output information of field
    friend std::ostream& operator<<(std::ostream& os, const Vertical& v);

private:
    idx_t size_;
    idx_t k_begin_;
    idx_t k_end_;
    std::vector<double> z_;
    double min_;
    double max_;
};

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

template <typename vector_t, typename Interval>
Vertical::Vertical(idx_t levels, const vector_t& z, const Interval& interval, const util::Config& config):
    Vertical(levels, z, config) {
    min_ = interval[0];
    max_ = interval[1];
}

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

template <typename vector_t>
Vertical::Vertical(idx_t levels, const vector_t& z, const util::Config&): size_{levels}, k_begin_{0}, k_end_{size_} {
    assert(size_ == static_cast<idx_t>(z.size()));
    z_.resize(size_);
    for (idx_t k = 0; k < size_; ++k) {
        z_[k] = z[k];
    }
    min_ = (size_ ? z[0] : 0.);
    max_ = (size_ ? z[size_ - 1] : 1.);
}

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

}  // namespace atlas
