package kr.co.compcareworker.Util.Api;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.google.gson.Gson;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import kr.co.compcareworker.Util.CustomView.MyProgress;
import kr.co.compcareworker.Util.FileUploadHelper;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class ApiClient {
    String BASE_URL = "https://www.compcare.co.kr/api/procs/";
    String TAG = "API";
    private String url;
    private Handler handler;
    private ArrayList<Uri> files;
    private Uri file;
    public Context context;

    void write_Log(HashMap<String, String> data) {
        Log.i("api", "sender = ApiClient : url = " + url);

        Object[] str = new Object[data.size()];
        String s = "";
        int i = 0;
        for (String key : data.keySet()) {
            str[i] = key + "/" + data.get(key);
            i++;
        }
        for (int j = 0; j < str.length; j++) {
            s += str[j].toString() + ", ";
        }

        Log.d("api", url + " : Data = " + s);
    }

    public ApiClient(HashMap<String, String> data, String url, Handler handler) {
        this.handler = handler;
        this.url = url;
        data.put("method", url);
        write_Log(data);
        createRetrofit(data);
    }

    public ApiClient(String url, Handler handler) {
        this.handler = handler;
        this.url = url;
        HashMap<String, String> data = new HashMap<>();
        data.put("method", url);
        write_Log(data);
        createRetrofit(data);
    }

    public ApiClient(HashMap<String, String> data, String url, ArrayList<Uri> files, Handler handler) {
        this.handler = handler;
        this.url = url;
        this.files = files;
        data.put("method", url);
        write_Log(data);
        createRetrofit_files(data, files);
    }

    public ApiClient(Context context, HashMap<String, String> data, String url, ArrayList<Uri> files, Handler handler) {
        this.context = context;
        this.handler = handler;
        this.url = url;
        this.files = files;
        data.put("method", url);
        write_Log(data);
        createRetrofit_files_progress(data, files);
    }

    public ApiClient(HashMap<String, String> data, String url, Uri file, Handler handler) {
        this.handler = handler;
        this.url = url;
        this.file = file;
        data.put("method", url);
        write_Log(data);
        createRetrofit_file(data, file);
    }

    private void createRetrofit(HashMap<String, String> data) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.MINUTES)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
//                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface service = retrofit.create(ApiInterface.class);
        Call<ResponseBody> getdata = null;
        if (data != null) {
            getdata = service.setdata(url, data);
        } else {
            getdata = service.seturl(url);
        }
        result(getdata);
    }

    private void createRetrofit_files(HashMap<String, String> data, ArrayList<Uri> file_path) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        ApiInterface service = retrofit.create(ApiInterface.class);

        Call<ResponseBody> getdata = service.setfiles(url, setParam(data), setParamFiles(file_path));
        result(getdata);
    }

    private void createRetrofit_files_progress(HashMap<String, String> data, ArrayList<Uri> file_path) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        ApiInterface service = retrofit.create(ApiInterface.class);

        Call<ResponseBody> getdata = service.setfiles(url, setParam(data), setParamFiles_progress(file_path));
        result(getdata);
    }

    private void createRetrofit_file(HashMap<String, String> data, Uri file_path) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        ApiInterface service = retrofit.create(ApiInterface.class);

        Call<ResponseBody> getdata = service.setfile(url, setParam(data), setParamFile(file_path));
        result(getdata);
    }

    //string
    private HashMap<String, RequestBody> setParam(HashMap<String, String> data) {
        HashMap<String, RequestBody> requestBodyHashMap = new HashMap<>();
        Iterator<String> keys = data.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            RequestBody requestBody = RequestBody.create(MultipartBody.FORM, Objects.requireNonNull(data.get(key)));
            requestBodyHashMap.put(key, requestBody);
        }

        return requestBodyHashMap;
    }

    private MultipartBody.Part[] setParamFiles(ArrayList<Uri> files) {
        FileUploadHelper helper = new FileUploadHelper();
        MultipartBody.Part[] part = new MultipartBody.Part[files.size()];
        for (int i = 0; i < files.size(); i++) {
            //File file = new File(files.get(i));
            File file = helper.getResizeFile(files.get(i));
            RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
            part[i] = MultipartBody.Part.createFormData("photo_arr[]", file.getName(), fileReqBody);
        }
        return part;
    }

    private MultipartBody.Part[] setParamFiles_progress(ArrayList<Uri> files) {
        FileUploadHelper helper = new FileUploadHelper();
        MultipartBody.Part[] part = new MultipartBody.Part[files.size()];

        MyProgress myProgress = new MyProgress(context, files.size());
        myProgress.show();

        for (int i = 0; i < files.size(); i++) {
            File file = helper.getResizeFile(files.get(i));

            int finalI = i;
            ProgressRequestBody fileReqBody = ProgressRequestBody.createImage(MediaType.parse("image/*"), file, files.size(), finalI, new ProgressRequestBody.UploadCallbacks() {

                @Override
                public void onProgressUpdate(String path, int percent) {
                    myProgress.setPercent(percent, finalI);
                }

                @Override
                public void onError() {
                    myProgress.closeDialog();
                }

                @Override
                public void onFinish() {
                    myProgress.uploadFinish();
                }
            });

            part[i] = MultipartBody.Part.createFormData("photo_arr[]", file.getName(), fileReqBody);
        }
        return part;
    }

    private MultipartBody.Part setParamFile(Uri uri) {
        FileUploadHelper helper = new FileUploadHelper();
        MultipartBody.Part part;
        //File file = new File(files.get(i));
        File file = helper.getResizeFile(uri);
        RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
        part = MultipartBody.Part.createFormData("photo1", file.getName(), fileReqBody);

        return part;
    }


    private void result(Call<ResponseBody> getdata) {

        if (getdata != null) {

            getdata.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

                    if (response.body() != null && response.isSuccessful()) {

                        //서버와의 통신이 성공했을 경우
                        String result = null;
                        Message msg = Message.obtain();
                        try {
                            result = response.body().string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        msg.obj = result;
                        msg.getData().putString("url", url);
                        msg.what = 1;
                        handler.sendMessage(msg);

                    } else {

                        //클라이언트에서 잘못된 요청을 보내거나 서버측에 문제가 있을 경우
                        Gson g = new Gson();
                        Message msg = Message.obtain();
                        msg.obj = g.toJson("서버에서 데이터를 불러오지 못했습니다.");
                        msg.getData().putString("url", url);
                        msg.what = -1;
                        handler.sendMessage(msg);
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    //인터넷 장애로 통신에 실패했을 경우
                    error(t);
                }
            });
        }
    }


    private void error(Throwable t) {
        Message msg = Message.obtain();
        String request = "네트워크를 확인해 주세요.";
        msg.obj = request;
        msg.what = -1;
        handler.sendMessage(msg);
        Log.e("onResponse", t.toString());
    }
}