package io.nexilis.service.core

import android.content.Context
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.core.content.FileProvider
import io.nexilis.service.tag
import okhttp3.Call
import okhttp3.Callback
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okio.buffer
import okio.sink
import java.io.File
import java.io.IOException


class Network {

    fun upload(url: String, file: File, completion: (Boolean) -> Unit) {
        val client = OkHttpClient()
        val body: RequestBody = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(
                    "file", file.name,
                    file.asRequestBody(null)
                )
                .addFormDataPart("other_field", "other_field_value")
                .build()
        } else {
            MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(
                    "file", file.name,
                    file.asRequestBody(null)
                )
                .addFormDataPart("other_field", "other_field_value")
                .build()
        }
        val request: Request = Request.Builder()
            .url(url)
            .addHeader("User-Agent", "Mozilla/5.0")
            .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
            .post(body)
            .build()
        Log.d(tag, "upload:enqueue:$url:${file.name}")
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Log.d(tag, "upload:onFailure")
                completion(false)
            }

            override fun onResponse(call: Call, response: Response) {
                Log.d(tag, "upload:onResponse:${response.code}")
                completion(response.code == 200)
            }
        })
    }

    fun upload(url: String, file: File) : Boolean {
        val client = OkHttpClient()
        val body: RequestBody = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(
                    "file", file.name,
                    file.asRequestBody(null)
                )
                .addFormDataPart("other_field", "other_field_value")
                .build()
        } else {
            MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(
                    "file", file.name,
                    file.asRequestBody(null)
                )
                .addFormDataPart("other_field", "other_field_value")
                .build()
        }
        val request: Request = Request.Builder()
            .url(url)
            .addHeader("User-Agent", "Mozilla/5.0")
            .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
            .post(body)
            .build()
        Log.d(tag, "upload:execute:$url:${file.name}:${file.length()}")
        client.newCall(request).execute().use { response ->
            return response.code == 200
        }
    }

    fun post(url: String, body: String, completion: (Boolean, body: String?) -> Unit) {
        val client = OkHttpClient()
        val requestBody: RequestBody =
            body.toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull())
        val request: Request = Request.Builder()
            .url(url)
            .addHeader("User-Agent", "Mozilla/5.0")
            .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
            .post(requestBody)
            .build()
        Log.d(tag, "post:enqueue:$url:$body")
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Log.d(tag, "post:onFailure")
                completion(false, null)
            }

            override fun onResponse(call: Call, response: Response) {
                Log.d(tag, "post:onResponse:${response.code}")
                completion(response.code == 200, response.body?.string())
            }
        })
    }

    fun download(context: Context, url: String): Uri? {
        val client = OkHttpClient()
        val request: Request = Request.Builder()
            .url(url)
            .addHeader("User-Agent", "Mozilla/5.0")
            .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
            .get()
            .build()
        Log.d(tag, "download:execute:$url")
        client.newCall(request).execute().use { response ->
            response.body?.let {
                val file = File(context.filesDir, url.split("/").last())
                val sink = file.sink().buffer()
                sink.writeAll(it.source())
                sink.close()
                Log.d(tag, "download:execute:file:${file.name} size:${file.length()} saved")
                val uri = FileProvider.getUriForFile(
                    context,
                    context.applicationContext.packageName + ".provider", file
                )
                Log.d(tag, "download:execute:uri:${uri}")
                return uri
            }
        }
        return null
    }

}