package kr.co.compcarecompany.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.concurrent.TimeUnit;

import kr.co.compcarecompany.Util.FileUploadHelper;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
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 HashMap<String, Uri> hashFiles;
    private Uri file;
    private 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);
    }

    void write_Log(HashMap<String, Object> data, String type) {
        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(HashMap<String, Object> data, String url, Handler handler, String type) {
        this.handler = handler;
        this.url = url;
        data.put("method", url);
        write_Log(data, type);
        createRetrofit(data, type);
    }


    public ApiClient(String s, 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(data, files);
    }

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

    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(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())
                .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);
        okHttpClient.dispatcher().executorService().shutdown();
    }

    ///////////////////////////////////////////////////////////////////////////
    private void createRetrofit(HashMap<String, Object> data, String type) {

        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())
                .build();

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

    /**
     * 파일 해시맵(키값이 필드명)
     */
    private void createRetrofit(HashMap<String, String> data, HashMap<String, Uri> hashFiles) {

        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(GsonConverterFactory.create())
                .build();

        ApiInterface service = retrofit.create(ApiInterface.class);

        Call<ResponseBody> getdata = service.setfiles(url, setParam(data), setParamFiles(hashFiles));
        result(getdata);
        okHttpClient.dispatcher().executorService().shutdown();
    }

    /**
     * 파일 어레이
     */
    private void createRetrofit(HashMap<String, String> data, ArrayList<Uri> file_path) {

        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(GsonConverterFactory.create())
                .build();

        ApiInterface service = retrofit.create(ApiInterface.class);

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

    /**
     * 파일 1개
     */
    private void createRetrofit(HashMap<String, String> data, Uri file_path) {

        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(GsonConverterFactory.create())
                .build();

        ApiInterface service = retrofit.create(ApiInterface.class);

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

    //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, data.get(key));
            requestBodyHashMap.put(key, requestBody);
        }

        return requestBodyHashMap;
    }

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

    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 = 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 setParamFile(Uri uri) {
        FileUploadHelper helper = new FileUploadHelper();
        MultipartBody.Part part;
        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);
                        handler.sendMessage(msg);
                        //동시 로그인 제한:내 기기와 DB에 저장된 IP가 다를 경우 message 에 404라고 보냄.
                        if (msg.obj.toString().contains("message\":\"404")){
                            msg.what = 2;
                            Log.d("msg@@@@", msg.obj.toString()+"와우");
                        }else {
                            msg.what = 1;
                            Log.d("msg@@@@", msg.obj.toString()+"정상");
                        }

                    } 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());
    }
}
