package org.wordpress.android.ui.people.utils;

import com.android.volley.VolleyError;
import com.wordpress.rest.RestRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wordpress.android.WordPress;
import org.wordpress.android.models.Person;
import org.wordpress.android.models.Role;
import org.wordpress.android.ui.people.utils.PeopleUtils.ValidateUsernameCallback.ValidationResult;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class PeopleUtils {
    // We limit followers we display to 1000 to avoid API performance issues
    public static int FOLLOWER_PAGE_LIMIT = 50;
    public static int FETCH_LIMIT = 20;

    public static void fetchUsers(final String blogId, final int localTableBlogId, final int offset,
                                  final FetchUsersCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    try {
                        JSONArray jsonArray = jsonObject.getJSONArray("users");
                        List<Person> people = peopleListFromJSON(jsonArray, localTableBlogId, Person.PersonType.USER);
                        int numberOfUsers = jsonObject.optInt("found");
                        boolean isEndOfList = (people.size() + offset) >= numberOfUsers;
                        callback.onSuccess(people, isEndOfList);
                    }
                    catch (JSONException e) {
                        AppLog.e(T.API, "JSON exception occurred while parsing the response for sites/%s/users: " + e);
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        Map<String, String> params = new HashMap<>();
        params.put("number", Integer.toString(PeopleUtils.FETCH_LIMIT));
        params.put("offset", Integer.toString(offset));
        params.put("order_by", "display_name");
        params.put("order", "ASC");
        String path = String.format("sites/%s/users", blogId);
        WordPress.getRestClientUtilsV1_1().get(path, params, null, listener, errorListener);
    }

    public static void fetchFollowers(final String blogId, final int localTableBlogId, final int page,
                                      final FetchFollowersCallback callback) {
        fetchFollowers(blogId, localTableBlogId, page, callback, false);
    }

    public static void fetchEmailFollowers(final String blogId, final int localTableBlogId, final int page,
                                           final FetchFollowersCallback callback) {
        fetchFollowers(blogId, localTableBlogId, page, callback, true);
    }

    private static void fetchFollowers(final String blogId, final int localTableBlogId, final int page,
                                       final FetchFollowersCallback callback, final boolean isEmailFollower) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    try {
                        JSONArray jsonArray = jsonObject.getJSONArray("subscribers");
                        Person.PersonType personType = isEmailFollower ?
                                Person.PersonType.EMAIL_FOLLOWER : Person.PersonType.FOLLOWER;
                        List<Person> people = peopleListFromJSON(jsonArray, localTableBlogId, personType);
                        int pageFetched = jsonObject.optInt("page");
                        int numberOfPages = jsonObject.optInt("pages");
                        boolean isEndOfList = page >= numberOfPages || page >= FOLLOWER_PAGE_LIMIT;
                        callback.onSuccess(people, pageFetched, isEndOfList);
                    }
                    catch (JSONException e) {
                        AppLog.e(T.API, "JSON exception occurred while parsing the response for " +
                                "sites/%s/stats/followers: " + e);
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        Map<String, String> params = new HashMap<>();
        params.put("max", Integer.toString(FETCH_LIMIT));
        params.put("page", Integer.toString(page));
        params.put("type", isEmailFollower ? "email" : "wp_com");
        String path = String.format("sites/%s/stats/followers", blogId);
        WordPress.getRestClientUtilsV1_1().get(path, params, null, listener, errorListener);
    }

    public static void fetchViewers(final String blogId, final int localTableBlogId, final int offset,
                                     final FetchViewersCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    try {
                        JSONArray jsonArray = jsonObject.getJSONArray("viewers");
                        List<Person> people = peopleListFromJSON(jsonArray, localTableBlogId, Person.PersonType.VIEWER);
                        int numberOfUsers = jsonObject.optInt("found");
                        boolean isEndOfList = (people.size() + offset) >= numberOfUsers;
                        callback.onSuccess(people, isEndOfList);
                    }
                    catch (JSONException e) {
                        AppLog.e(T.API, "JSON exception occurred while parsing the response for " +
                                "sites/%s/viewers: " + e);
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        int page = (offset / FETCH_LIMIT) + 1;
        Map<String, String> params = new HashMap<>();
        params.put("number", Integer.toString(FETCH_LIMIT));
        params.put("page", Integer.toString(page));
        String path = String.format("sites/%s/viewers", blogId);
        WordPress.getRestClientUtilsV1_1().get(path, params, null, listener, errorListener);
    }

    public static void updateRole(final String blogId, long personID, Role newRole, final int localTableBlogId,
                                  final UpdateUserCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    try {
                        Person person = Person.userFromJSON(jsonObject, localTableBlogId);
                        if (person != null) {
                            callback.onSuccess(person);
                        } else {
                            AppLog.e(T.API, "Couldn't map jsonObject + " + jsonObject + " to person model.");
                            callback.onError();
                        }
                    } catch (JSONException e) {
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        Map<String, String> params = new HashMap<>();
        params.put("roles", newRole.toRESTString());
        String path = String.format("sites/%s/users/%d", blogId, personID);
        WordPress.getRestClientUtilsV1_1().post(path, params, null, listener, errorListener);
    }

    public static void removeUser(String blogId, final long personID, final int localTableBlogId,
                                  final RemovePersonCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    // check if the call was successful
                    boolean success = jsonObject.optBoolean("success");
                    if (success) {
                        callback.onSuccess(personID, localTableBlogId);
                    } else {
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        String path = String.format("sites/%s/users/%d/delete", blogId, personID);
        WordPress.getRestClientUtilsV1_1().post(path, listener, errorListener);
    }

    public static void removeFollower(String blogId, final long personID, final int localTableBlogId,
                                      Person.PersonType personType, final RemovePersonCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    // check if the call was successful
                    boolean success = jsonObject.optBoolean("deleted");
                    if (success) {
                        callback.onSuccess(personID, localTableBlogId);
                    } else {
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        String path;
        if (personType == Person.PersonType.EMAIL_FOLLOWER) {
            path = String.format("sites/%s/email-followers/%d/delete", blogId, personID);
        } else {
            path = String.format("sites/%s/followers/%d/delete", blogId, personID);
        }
        WordPress.getRestClientUtilsV1_1().post(path, listener, errorListener);
    }

    public static void removeViewer(String blogId, final long personID, final int localTableBlogId,
                                    final RemovePersonCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    // check if the call was successful
                    boolean success = jsonObject.optBoolean("deleted");
                    if (success) {
                        callback.onSuccess(personID, localTableBlogId);
                    } else {
                        callback.onError();
                    }
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        String path = String.format("sites/%s/viewers/%d/delete", blogId, personID);
        WordPress.getRestClientUtilsV1_1().post(path, listener, errorListener);
    }

    private static List<Person> peopleListFromJSON(JSONArray jsonArray, int localTableBlogId,
                                                   Person.PersonType personType) throws JSONException {
        if (jsonArray == null) {
            return null;
        }

        ArrayList<Person> peopleList = new ArrayList<>(jsonArray.length());

        for (int i = 0; i < jsonArray.length(); i++) {
            Person person;
            if (personType == Person.PersonType.USER) {
                person = Person.userFromJSON(jsonArray.optJSONObject(i), localTableBlogId);
            } else if (personType == Person.PersonType.VIEWER) {
                person = Person.viewerFromJSON(jsonArray.optJSONObject(i), localTableBlogId);
            } else {
                boolean isEmailFollower = (personType == Person.PersonType.EMAIL_FOLLOWER);
                person = Person.followerFromJSON(jsonArray.optJSONObject(i), localTableBlogId, isEmailFollower);
            }
            if (person != null) {
                peopleList.add(person);
            }
        }

        return peopleList;
    }

    public interface FetchUsersCallback extends Callback {
        void onSuccess(List<Person> peopleList, boolean isEndOfList);
    }

    public interface FetchFollowersCallback extends Callback {
        void onSuccess(List<Person> peopleList, int pageFetched, boolean isEndOfList);
    }

    public interface FetchViewersCallback extends Callback {
        void onSuccess(List<Person> peopleList, boolean isEndOfList);
    }

    public interface RemovePersonCallback extends Callback {
        void onSuccess(long personID, int localTableBlogId);
    }

    public interface UpdateUserCallback extends Callback {
        void onSuccess(Person person);
    }

    public interface Callback {
        void onError();
    }

    public static void validateUsernames(final List<String> usernames, Role role, String dotComBlogId, final
            ValidateUsernameCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (jsonObject != null && callback != null) {
                    JSONObject errors = jsonObject.optJSONObject("errors");

                    int errorredUsernameCount = 0;

                    if (errors != null) {
                        for (String username : usernames) {
                            JSONObject userError = errors.optJSONObject(username);

                            if (userError == null) {
                                continue;
                            }

                            errorredUsernameCount++;

                            switch (userError.optString("code")) {
                                case "invalid_input":
                                    switch (userError.optString("message")) {
                                        case "User not found":
                                            callback.onUsernameValidation(username, ValidationResult.USER_NOT_FOUND);
                                            continue;
                                        case "Invalid email":
                                            callback.onUsernameValidation(username, ValidationResult.INVALID_EMAIL);
                                            continue;
                                    }
                                    break;
                                case "invalid_input_has_role":
                                    callback.onUsernameValidation(username, ValidationResult.ALREADY_MEMBER);
                                    continue;
                                case "invalid_input_following":
                                    callback.onUsernameValidation(username, ValidationResult.ALREADY_FOLLOWING);
                                    continue;
                                case "invalid_user_blocked_invites":
                                    callback.onUsernameValidation(username, ValidationResult.BLOCKED_INVITES);
                                    continue;
                            }

                            callback.onError();
                            callback.onValidationFinished();
                            return;
                        }
                    }

                    JSONArray succeededUsernames = jsonObject.optJSONArray("success");
                    if (succeededUsernames == null) {
                        callback.onError();
                        callback.onValidationFinished();
                        return;
                    }

                    int succeededUsernameCount = 0;

                    for (int i = 0; i < succeededUsernames.length(); i++) {
                        String username = succeededUsernames.optString(i);
                        if (usernames.contains(username)) {
                            succeededUsernameCount++;
                            callback.onUsernameValidation(username, ValidationResult.USER_FOUND);
                        }
                    }

                    if (errorredUsernameCount + succeededUsernameCount != usernames.size()) {
                        callback.onError();
                        callback.onValidationFinished();
                    }

                    callback.onValidationFinished();
                }
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(AppLog.T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        String path = String.format("sites/%s/invites/validate", dotComBlogId);
        Map<String, String> params = new HashMap<>();
        for (String username : usernames) {
            params.put("invitees[" + username + "]", username); // specify an array key so to make the map key unique
        }
        params.put("role", role.toRESTString());
        WordPress.getRestClientUtilsV1_1().post(path, params, null, listener, errorListener);
    }

    public interface ValidateUsernameCallback {
        enum ValidationResult {
            USER_NOT_FOUND,
            ALREADY_MEMBER,
            ALREADY_FOLLOWING,
            BLOCKED_INVITES,
            INVALID_EMAIL,
            USER_FOUND
        }

        void onUsernameValidation(String username, ValidationResult validationResult);
        void onValidationFinished();
        void onError();
    }

    public static void sendInvitations(final List<String> usernames, Role role, String message, String dotComBlogId,
                                       final InvitationsSendCallback callback) {
        com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (callback == null) {
                    return;
                }

                if (jsonObject == null) {
                    callback.onError();
                    return;
                }

                Map<String, String> failedUsernames = new LinkedHashMap<>();

                JSONObject errors = jsonObject.optJSONObject("errors");
                if (errors != null) {
                    for (String username : usernames) {
                        JSONObject userError = errors.optJSONObject(username);

                        if (userError != null) {
                            failedUsernames.put(username, userError.optString("message"));
                        }
                    }
                }

                List<String> succeededUsernames = new ArrayList<>();
                JSONArray succeededUsernamesJson = jsonObject.optJSONArray("sent");
                if (succeededUsernamesJson == null) {
                    callback.onError();
                    return;
                }

                for (int i = 0; i < succeededUsernamesJson.length(); i++) {
                    String username = succeededUsernamesJson.optString(i);
                    if (usernames.contains(username)) {
                        succeededUsernames.add(username);
                    }
                }

                if (failedUsernames.size() + succeededUsernames.size() != usernames.size()) {
                    callback.onError();
                }

                callback.onSent(succeededUsernames, failedUsernames);
            }
        };

        RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                AppLog.e(AppLog.T.API, volleyError);
                if (callback != null) {
                    callback.onError();
                }
            }
        };

        String path = String.format("sites/%s/invites/new", dotComBlogId);
        Map<String, String> params = new HashMap<>();
        for (String username : usernames) {
            params.put("invitees[" + username + "]", username); // specify an array key so to make the map key unique
        }
        params.put("role", role.toRESTString());
        params.put("message", message);
        WordPress.getRestClientUtilsV1_1().post(path, params, null, listener, errorListener);
    }

    public interface InvitationsSendCallback {
        void onSent(List<String> succeededUsernames, Map<String, String> failedUsernameErrors);
        void onError();
    }
}
