/*
 * Copyright (c) 2016, 2017 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
namespace arm_compute
{
inline Window::Window(const Window &src)
    : _dims(), _thread_id(src._thread_id), _num_threads(src._num_threads)
{
    for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
    {
        set(i, src[i]);
    }
}

inline constexpr const Window::Dimension &Window::operator[](const size_t dimension) const
{
    // Precondition: dimension < Coordinates::num_max_dimensions
    return _dims.at(dimension);
}
inline void Window::set(const size_t dimension, const Window::Dimension &dim)
{
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
    _dims[dimension] = dim;
}

inline void Window::shift(const size_t dimension, const int shift_value)
{
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
    Window::Dimension &d = _dims[dimension];
    d                    = Window::Dimension(d.start() + shift_value, d.end() + shift_value, d.step());
}

inline void Window::adjust(size_t dimension, int adjust_value, bool is_at_start)
{
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
    Window::Dimension &d = _dims[dimension];

    if(is_at_start)
    {
        d = Window::Dimension(d.start() + adjust_value, d.end(), d.step());
    }
    else
    {
        d = Window::Dimension(d.start(), d.end() + adjust_value, d.step());
    }
}

inline void Window::scale(const size_t dimension, float scale_value)
{
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
    Window::Dimension &d           = _dims[dimension];
    const int          scaled_step = d.step() * scale_value;
    const int          scaled_end  = ceil_to_multiple(d.end() * scale_value, scaled_step);
    d                              = Window::Dimension(d.start() * scale_value, scaled_end, scaled_step);
}

inline void Window::set_dimension_step(const size_t dimension, const int step)
{
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);
    _dims[dimension].set_step(step);
}

inline void Window::validate() const
{
    for(size_t i = 0; i < Coordinates::num_max_dimensions; ++i)
    {
        ARM_COMPUTE_ERROR_ON(_dims[i].step() == 0);
        ARM_COMPUTE_ERROR_ON(_dims[i].end() <= _dims[i].start());
        ARM_COMPUTE_ERROR_ON((_dims[i].end() - _dims[i].start()) % _dims[i].step());
    }
}

inline constexpr size_t Window::num_iterations(size_t dimension) const
{
    // Precondition: dimension < Coordinates::num_max_dimensions
    // Precondition: (end - start) % step == 0
    return (_dims.at(dimension).end() - _dims.at(dimension).start()) / _dims.at(dimension).step();
}

inline Window Window::split_window(const size_t dimension, const size_t id, const size_t total) const
{
    ARM_COMPUTE_ERROR_ON(id >= total);
    ARM_COMPUTE_ERROR_ON(dimension >= Coordinates::num_max_dimensions);

    Window out;

    for(size_t d = 0; d < Coordinates::num_max_dimensions; ++d)
    {
        if(d == dimension)
        {
            int start          = _dims[d].start();
            int end            = _dims[d].end();
            int per_sub_window = (num_iterations(d) / total) * _dims[d].step();

            start += id * per_sub_window;

            if(id != total - 1)
            {
                end = start + per_sub_window;
            }

            out.set(d, Dimension(start, end, _dims[d].step()));
        }
        else
        {
            out.set(d, _dims[d]);
        }
    }

    return out;
}

template <unsigned int window_dimension>
inline bool Window::slide_window_slice(Window &slice) const
{
    for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
    {
        // Did we reach the end of this dimension?
        const int v = slice._dims[n].start() + 1;

        if(v < _dims[n].end())
        {
            // No: increment
            slice._dims[n] = Dimension(v, v + 1, 1);

            // Reset lower dimensions:
            for(unsigned int lower = window_dimension; lower < n; ++lower)
            {
                slice._dims[lower] = Dimension(_dims[lower].start(), _dims[lower].start() + 1, 1);
            }
            return true;
        }
    }

    // It was the last slice
    return false; // Iteration over
}

template <unsigned int window_dimension>
inline Window          Window::first_slice_window() const
{
    Window slice;

    std::copy_n(_dims.begin(), window_dimension, slice._dims.begin());

    //Initialise higher dimensions to be the first slice.
    for(unsigned int n = window_dimension; n < Coordinates::num_max_dimensions; ++n)
    {
        slice._dims[n] = Dimension(_dims[n].start(), _dims[n].start() + 1, 1);
    }

    return slice;
}

inline void Window::use_tensor_dimensions(const ITensorInfo *info, const size_t first_dimension)
{
    for(unsigned int n = first_dimension; n < info->num_dimensions(); ++n)
    {
        set(n, Window::Dimension(0, std::max(info->dimension(n), static_cast<size_t>(1))));
    }
}
}
