/*
 * Copyright (c) 2017-2018 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.
 */
#ifndef __ARM_COMPUTE_TEST_TENSOR_CACHE_H__
#define __ARM_COMPUTE_TEST_TENSOR_CACHE_H__

#include "RawTensor.h"

#include "support/Mutex.h"

#include <map>
#include <mutex>
#include <utility>

namespace arm_compute
{
namespace test
{
/** Stores @ref RawTensor categorised by the image they are created from
 * including name, format and channel.
 */
class TensorCache
{
public:
    /** Search the cache for a tensor of created from the specified image and
     * format.
     *
     * @param[in] key Key to look up the tensor. Consists of image name and format.
     *
     * @return The cached tensor matching the image name and format if found. A
     *         nullptr otherwise.
     */
    RawTensor *find(std::tuple<const std::string &, Format> key);

    /** Search the cache for a tensor of created from the specified image,
     * format and channel.
     *
     * @param[in] key Key to look up the tensor. Consists of image name, format and channel.
     *
     * @return The cached tensor matching the image name and format if found. A
     *         nullptr otherwise.
     */
    RawTensor *find(std::tuple<const std::string &, Format, Channel> key);

    /** Add the given tensor to the cache. Can later be found under the given
     * image name and format.
     *
     * @param[in] key Key under which to store the tensor. Consists of image name and format.
     * @param[in] raw Raw tensor to be stored.
     *
     * @return A reference to the cached tensor.
     */
    RawTensor &add(std::tuple<const std::string &, Format> key, RawTensor raw);

    /** Add the given tensor to the cache. Can later be found under the given
     * image name, format and channel.
     *
     * @param[in] key Key under which to store the tensor. Consists of image name, format and channel.
     * @param[in] raw Raw tensor to be stored.
     *
     * @return A reference to the cached tensor.
     */
    RawTensor &add(std::tuple<const std::string &, Format, Channel> key, RawTensor raw);

private:
    using FormatMap  = std::map<std::tuple<std::string, Format>, RawTensor>;
    using ChannelMap = std::map<std::tuple<std::string, Format, Channel>, RawTensor>;

    FormatMap          _raw_tensor_cache{};
    ChannelMap         _raw_tensor_channel_cache{};
    arm_compute::Mutex _raw_tensor_cache_mutex{};
    arm_compute::Mutex _raw_tensor_channel_cache_mutex{};
};

inline RawTensor *TensorCache::find(std::tuple<const std::string &, Format> key)
{
    const auto it = _raw_tensor_cache.find(key);
    return it == _raw_tensor_cache.end() ? nullptr : &it->second;
}

inline RawTensor *TensorCache::find(std::tuple<const std::string &, Format, Channel> key)
{
    const auto it = _raw_tensor_channel_cache.find(key);
    return it == _raw_tensor_channel_cache.end() ? nullptr : &it->second;
}

inline RawTensor &TensorCache::add(std::tuple<const std::string &, Format> key, RawTensor raw)
{
    std::lock_guard<arm_compute::Mutex> lock(_raw_tensor_cache_mutex);
    return std::get<0>(_raw_tensor_cache.emplace(std::move(key), std::move(raw)))->second;
}

inline RawTensor &TensorCache::add(std::tuple<const std::string &, Format, Channel> key, RawTensor raw)
{
    std::lock_guard<arm_compute::Mutex> lock(_raw_tensor_channel_cache_mutex);
    return std::get<0>(_raw_tensor_channel_cache.emplace(std::move(key), std::move(raw)))->second;
}
} // namespace test
} // namespace arm_compute
#endif /* __ARM_COMPUTE_TEST_TENSOR_CACHE_H__ */
