package com.seatel.mobilehall.data.network;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.android.volley.NoConnectionError;
import com.android.volley.Request;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;

import org.json.JSONArray;
import org.json.JSONObject;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * Created by Kevin on 9/26/2016.
 */

public abstract class SeatelSuperRequest<T> extends CoreRequest<T> {

    private String contentType = "application/json; charset=utf-8";
    private int method = Request.Method.GET;

    public abstract String getLanguageCode();

    public SeatelSuperRequest(Context context) {
        super(context);
    }

    /**
     * default GET
     */
    @Override
    public int getMethod() {
        return method;
    }

    public void setMethod(int method) {
        this.method = method;
    }

    @Override
    public abstract String getBaseUrl();

    public abstract String getBaseController();

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public String getContentType() {
        return contentType;
    }

    @Override
    public Map<String, String> onCreateHeader(Map<String, String> header) {
        header = new HashMap<>();
        header.put("X-App-Version", Devices.INSTANCE.getAppVersionName(getContext()));
        header.put("X-Language", getLanguageCode().toLowerCase());
        header.put("X-Latitude", "");
        header.put("X-Longitude", "");
        header.put("X-Timestamp", getTimestamp());
        header.put("X-Timezone", getLocalTimezone());
        header.put("X-Platform", "android");
        header.put("X-OS-Version", Devices.INSTANCE.getDeviceOSVersion());
        header.put("X-UDID", Devices.INSTANCE.getDeviceID(getContext()));
        header.put("X-App-Signature", getAppSignatures());
        if (getMethod() == Request.Method.POST || getMethod() == Request.Method.PUT) {
            if (getContentType() != null)
                header.put("Content-Type", contentType);
        }
        header.putAll(getAuthHeader());
        Log.d("HEADER:>>>", this.getClass().getSimpleName() + "(" + getContext().getClass().getSimpleName() + ") : " + header.toString());
        return header;
    }

    public String getTimestamp() {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
        TimeZone tz = TimeZone.getTimeZone("UTC");
        df.setTimeZone(tz);
        return df.format(new Date());
    }

    public abstract String getFunctionName();

    public String getAppSignatures() {
        return "";
    }

    public String getLocalTimezone() {
        Calendar cal = Calendar.getInstance();
        TimeZone tz = cal.getTimeZone();
        return tz.getID();
    }

    @Override
    public void execute() {
        super.execute();
        try {
            Log.d("EXECUTE:>>>", this.getClass().getSimpleName() + "(" + getContext().getClass().getSimpleName() + ") : "
                    + getMethodName(getMethod()) + " " + getRequestUrl());
            if (!TextUtils.isEmpty(onGetBodyRequest()))
                Log.d("EXECUTE:>>>", this.getClass().getSimpleName() + " JSON data " + new JSONObject(onGetBodyRequest()).toString(1));
            else
                Log.d("EXECUTE:>>>", this.getClass().getSimpleName() + " JSON data null");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getErrorMessageFrom(VolleyError volleyError, String defaultMsg) {
        if (volleyError instanceof NoConnectionError) {
            return "Please check your internet connection and try again!";
        } else if (volleyError instanceof TimeoutError) {
            return "Please check your internet connection and try again!";
        }
        try {
            String errorMessage = new String(volleyError.networkResponse.data);
            JSONObject jsonObject = new JSONObject(errorMessage);
            JSONArray jsonArrayError = jsonObject.optJSONArray("errors");
            if (jsonArrayError != null && jsonArrayError.length() > 0) {
                JSONObject jsonObjectError = jsonArrayError.getJSONObject(0);
                return jsonObjectError.optString("message", defaultMsg);
            } else {
                jsonObject.optString("message", defaultMsg);
            }
            return jsonObject.optString("message", defaultMsg);
        } catch (Exception e) {
            try {
                String msg = new String(volleyError.networkResponse.data);
                if (TextUtils.isEmpty(msg)) {
                    msg = defaultMsg;
                }
                return msg;
            } catch (Exception ee) {
                return defaultMsg;
            }
        }
    }

    public static String getErrorMessageFrom(VolleyError volleyError) {
        return getErrorMessageFrom(volleyError, "");
    }

    public abstract Map<String, String> getAuthHeader();

    /**
     * use for display method request name as string only
     */
    private String getMethodName(int method) {
        if (method == Request.Method.GET)
            return "GET";
        if (method == Request.Method.POST)
            return "POST";
        if (method == Request.Method.PUT)
            return "PUT";
        if (method == Request.Method.DELETE)
            return "DELETE";
        if (method == Request.Method.HEAD)
            return "HEAD";
        if (method == Request.Method.OPTIONS)
            return "OPTIONS";
        if (method == Request.Method.TRACE)
            return "TRACE";
        if (method == Request.Method.PATCH)
            return "PATCH";
        return "UNKNOWN METHOD";
    }
}
