/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SampleDriverUtils.h"

#include <android-base/logging.h>

#include "SampleDriver.h"

namespace android {
namespace nn {
namespace sample_driver {

void notify(const sp<V1_0::IPreparedModelCallback>& callback, const V1_3::ErrorStatus& status,
            const sp<SamplePreparedModel>& preparedModel) {
    const auto ret = callback->notify(convertToV1_0(status), preparedModel);
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IPreparedModelCallback::notify: " << ret.description();
    }
}

void notify(const sp<V1_2::IPreparedModelCallback>& callback, const V1_3::ErrorStatus& status,
            const sp<SamplePreparedModel>& preparedModel) {
    const auto ret = callback->notify_1_2(convertToV1_0(status), preparedModel);
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IPreparedModelCallback::notify_1_2: "
                   << ret.description();
    }
}

void notify(const sp<V1_3::IPreparedModelCallback>& callback, const V1_3::ErrorStatus& status,
            const sp<SamplePreparedModel>& preparedModel) {
    const auto ret = callback->notify_1_3(status, preparedModel);
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IPreparedModelCallback::notify_1_3: "
                   << ret.description();
    }
}

void notify(const sp<V1_0::IExecutionCallback>& callback, const V1_3::ErrorStatus& status,
            const hardware::hidl_vec<V1_2::OutputShape>&, V1_2::Timing) {
    const auto ret = callback->notify(convertToV1_0(status));
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IExecutionCallback::notify: " << ret.description();
    }
}

void notify(const sp<V1_2::IExecutionCallback>& callback, const V1_3::ErrorStatus& status,
            const hardware::hidl_vec<V1_2::OutputShape>& outputShapes, V1_2::Timing timing) {
    const auto ret = callback->notify_1_2(convertToV1_0(status), outputShapes, timing);
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IExecutionCallback::notify_1_2: " << ret.description();
    }
}

void notify(const sp<V1_3::IExecutionCallback>& callback, const V1_3::ErrorStatus& status,
            const hardware::hidl_vec<V1_2::OutputShape>& outputShapes, V1_2::Timing timing) {
    const auto ret = callback->notify_1_3(status, outputShapes, timing);
    if (!ret.isOk()) {
        LOG(ERROR) << "Error when calling IExecutionCallback::notify_1_3" << ret.description();
    }
}

}  // namespace sample_driver
}  // namespace nn
}  // namespace android
