package ru.yandex.autotests.direct.web.api.core;

import java.io.IOException;
import java.lang.annotation.Annotation;

import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.Call;
import retrofit2.Converter;
import retrofit2.Response;

import ru.yandex.autotests.direct.utils.BaseSteps;
import ru.yandex.autotests.irt.testutils.allure.AllureUtils;
import ru.yandex.autotests.irt.testutils.json.JsonUtils;
import ru.yandex.qatools.allure.annotations.Step;

public abstract class DirectWebApiBaseSteps<T> extends BaseSteps<DirectWebApiStepsContext> {
    private T apiService;
    private Logger logger;
    private Class<T> apiServiceClass;

    public DirectWebApiBaseSteps(Class<T> apiServiceClass) {
        this.apiServiceClass = apiServiceClass;
        logger = LoggerFactory.getLogger(DirectWebApiBaseSteps.class);
    }

    protected T getOrCreateApiService() {
        if (apiService == null) {
            apiService = getContext().getApiClient().createService(apiServiceClass);
        }
        return apiService;
    }

    protected Logger log() {
        return logger;
    }

    @Step("Web api call")
    protected <R> Response<R> execute(Call<R> call) {
        Response<R> result;
        try {
            result = call.execute();
            if (result.isSuccessful()) {
                AllureUtils.addJsonAttachment("Response", JsonUtils.toString(result.body()));
            }
        } catch (IOException e) {
            throw new DirectWebApiError("Exception while processing web api request", e);
        }
        return result;
    }

    protected <R> Response<R> executeSafe(Call<R> call) {
        Response<R> response = execute(call);
        if (!response.isSuccessful()) {
            throw new DirectWebApiError("Web api returned error: " + response.message());
        }
        return response;
    }

    protected <R> Converter<ResponseBody, R> getConverter(Class<R> toClass) {
        return getContext().getApiClient().getAdapterBuilder().build()
                .responseBodyConverter(toClass, new Annotation[0]);
    }

    public DirectWebApiBaseSteps withApiService(T apiService) {
        this.apiService = apiService;
        return this;
    }

    public Class<T> getApiServiceClass() {
        return apiServiceClass;
    }

    public T getApiService() {
        return apiService;
    }
}
