/*
 * *************************************************************************************************
 *                                 Copyright 2017 Universum Studios
 * *************************************************************************************************
 *                  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.
 * *************************************************************************************************
 */
package universum.studios.gradle.github.service.api

import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import universum.studios.gradle.github.extension.RepositoryExtension
import universum.studios.gradle.github.service.api.interceptor.HeaderInterceptor
import universum.studios.gradle.github.service.api.interceptor.OAuthRequestInterceptor

/**
 * Class which may be used as base for a concrete API implementation. This base class creates a
 * services PROXY implementation for the provided *servicesInterface* which may be later accessed
 * via *services* property.
 *
 * @author Martin Albedinsky
 * @since 1.0
 *
 * @param T Type of the services for which to create the PROXY.
 * @param repository The repository for which may be performed service calls through the api.
 * @param servicesInterface Services interface for which to create its PROXY that may be used for
 * service call creation.
 * @constructor Creates a new instance of BaseApi with the specified services interface.
 */
internal abstract class BaseApi<out T>(
        /**
         * Repository for which should this api provide service calls.
         */
        internal val repository: RepositoryExtension, servicesInterface: Class<T>) : Api {

    /*
     * Companion ===================================================================================
     */

    /**
     */
    internal companion object {

        /**
         * Boolean flag indicating whether to debug API requests/responses or not.
         */
        private const val DEBUG = false

        /**
         * Name of the **Accept** header.
         */
        const val HEADER_ACCEPT_NAME = "Accept"

        /**
         * Value for the **Accept** header.
         */
        const val HEADER_ACCEPT_VALUE = "application/vnd.github.v3+json"
    }

    /*
	 * Interface ===================================================================================
	 */

    /*
     * Members =====================================================================================
     */

    /**
     * PROXY instance of the services interface supplied for this API.
     */
    internal val services: T = Retrofit.Builder()
            .baseUrl(Api.BASE_URL)
            .client(okhttp3.OkHttpClient.Builder()
                    .addInterceptor(HeaderInterceptor(HEADER_ACCEPT_NAME, HEADER_ACCEPT_VALUE))
                    .addInterceptor(OAuthRequestInterceptor().apply { setToken(repository.accessToken) })
                    .addInterceptor(HttpLoggingInterceptor().setLevel(
                            if (DEBUG) HttpLoggingInterceptor.Level.BODY
                            else HttpLoggingInterceptor.Level.NONE
                    ))
                    .build()
            )
            .addConverterFactory(MoshiConverterFactory.create())
            .build().create(servicesInterface)

    /*
     * Constructors ================================================================================
     */

    /*
     * Methods =====================================================================================
     */

    /*
     */
    override fun getRepository() = repository

    /*
     * Inner classes ===============================================================================
     */
}