package com.namelessmc.java_api;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.namelessmc.java_api.exception.NamelessException;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.*;

public class FilteredUserListBuilder {

	private final @NonNull NamelessAPI api;
	private @Nullable Map<UserFilter<?>, Object> filters;
	private @NonNull String operator = "AND";

	FilteredUserListBuilder(@NonNull NamelessAPI api) {
		this.api = api;
	}

	public <T> @NonNull FilteredUserListBuilder withFilter(final @NonNull UserFilter<T> filter,
														   final @NonNull T value) {
		if (filters == null) {
			filters = new HashMap<>();
		}

		filters.put(
				Objects.requireNonNull(filter, "Filter is null"),
				Objects.requireNonNull(value, "Value for filter " + filter.name() + " is null")
		);
		return this;
	}

	public @NonNull FilteredUserListBuilder all() {
		this.operator = "AND";
		return this;
	}

	public @NonNull FilteredUserListBuilder any() {
		this.operator = "OR";
		return this;
	}

	public JsonObject makeRawRequest() throws NamelessException {
		final Object[] parameters;
		if (filters != null) {
			int filterCount = filters.size();
			parameters = new Object[filterCount * 2 + 2];
			parameters[0] = "operator";
			parameters[1] = operator;
			int i = 2;
			for (Map.Entry<UserFilter<?>, Object> filter : this.filters.entrySet()) {
				parameters[i++] = filter.getKey().name();
				parameters[i++] = filter.getValue();
			}
		} else {
			parameters = new Object[0];
		}

		return this.api.requests().get("users", parameters);
	}

	public @NonNull List<@NonNull NamelessUser> makeRequest() throws NamelessException {
		final JsonObject response = this.makeRawRequest();
		final JsonArray array = response.getAsJsonArray("users");
		final List<NamelessUser> users = new ArrayList<>(array.size());
		for (final JsonElement e : array) {
			final JsonObject o = e.getAsJsonObject();
			final int id = o.get("id").getAsInt();
			users.add(new NamelessUser(this.api, id));
		}
		return Collections.unmodifiableList(users);
	}

}

@@ -1327,16 +1327,20 @@
  Object%5B
+4 + 
 filterCo
@@ -1350,13 +1350,23 @@
  * 2
- + 2%5D
+%5D;%0A%09%09%09int i = 0
 ;%0A%09%09
@@ -1377,17 +1377,19 @@
 ameters%5B
-0
+i++
 %5D = %22ope
@@ -1414,9 +1414,11 @@
 ers%5B
-1
+i++
 %5D = 
@@ -1434,17 +1434,57 @@
 %0A%09%09%09
-int i = 2
+parameters%5Bi++%5D = %22limit%22;%0A%09%09%09parameters%5Bi++%5D = 0
 ;%0A%09%09

disable user list limit, we don't support it