package com.namelessmc.java_api;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.util.Objects;
import java.util.stream.StreamSupport;

public class Website implements LanguageEntity {

	private final @NonNull String version;
	private final @Nullable Update update;
	private final @NonNull String@NonNull[] modules;
	private final @NonNull String rawLanguage;

	Website(final @NonNull JsonObject json) throws NamelessException {
		Objects.requireNonNull(json, "Provided json object is null");

		if (!json.has("nameless_version")) {
			// This is usually the point where people run into issues if the response is not from NamelessMC
			// but from something else like a proxy or denial of service protection system, so we throw a useful
			// exception.
			throw new NamelessException("Website didn't include namelessmc_version in the info response. Is the response from NamelessMC?");
		}

		this.version = json.get("nameless_version").getAsString();

		this.modules = StreamSupport.stream(json.get("modules").getAsJsonArray().spliterator(), false)
				.map(JsonElement::getAsString)
				.toArray(String[]::new);

		if (json.has("version_update")) {
			final JsonObject updateJson = json.get("version_update").getAsJsonObject();
			final boolean updateAvailable = updateJson.get("update").getAsBoolean();
			if (updateAvailable) {
				final String updateVersion = updateJson.get("version").getAsString();
				final boolean isUrgent = updateJson.get("urgent").getAsBoolean();
				this.update = new Update(isUrgent, updateVersion);
			} else {
				this.update = null;
			}
		} else {
			this.update = null;
		}

		this.rawLanguage = json.get("locale").getAsString();
	}

	public @NonNull String rawVersion() {
		return this.version;
	}

	public @Nullable NamelessVersion parsedVersion() {
		return NamelessVersion.parse(this.version);
	}

	/**
	 * @return Information about an update, or empty if no update is available.
	 */
	public @Nullable Update update() {
		return this.update;
	}

	public @NonNull String@NonNull [] getModules() {
		return this.modules;
	}

	@Override
	public @NonNull String rawLocale() throws NamelessException {
		return this.rawLanguage;
	}

	public static class Update {

		private final boolean isUrgent;
		private final String version;

		Update(final boolean isUrgent, final String version) {
			this.isUrgent = isUrgent;
			this.version = version;
		}

		public boolean isUrgent() {
			return this.isUrgent;
		}

		public String rawVersion() {
			return this.version;
		}

		public @Nullable NamelessVersion parsedVersion() {
			return NamelessVersion.parse(this.version);
		}

		public @Nullable NamelessVersion getParsedVersion() {
			return NamelessVersion.parse(this.version);
		}

	}

}

@@ -153,76 +153,39 @@
 al.N
-onN
 ull
+able
 ;%0A
+%0A
 import 
-org.checkerframework.checker.nullness.qual.Nullable;%0A
+java.util.Set;
 %0Aimp
@@ -198,22 +198,32 @@
 va.util.
-Obj
+stream.Coll
 ect
+or
 s;%0Aimpor
@@ -318,33 +318,24 @@
 ivate final 
-@NonNull 
 String versi
@@ -397,33 +397,19 @@
 nal 
-@NonNull String@NonNull%5B%5D
+Set%3CString%3E
  mod
@@ -429,25 +429,16 @@
 e final 
-@NonNull 
 String r
@@ -465,25 +465,16 @@
 e(final 
-@NonNull 
 JsonObje
@@ -513,73 +513,8 @@
 n %7B%0A
-%09%09Objects.requireNonNull(json, %22Provided json object is null%22);%0A%0A
 %09%09if
@@ -1109,29 +1109,46 @@
 %09%09%09.
-toArray(String%5B%5D::new
+collect(Collectors.toUnmodifiableSet()
 );%0A%0A
@@ -1706,33 +1706,24 @@
 %09%7D%0A%0A%09public 
-@NonNull 
 String rawVe
@@ -2022,39 +2022,21 @@
 lic 
-@NonNull String@NonNull %5B%5D getM
+Set%3CString%3E m
 odul
@@ -2092,17 +2092,8 @@
 lic 
-@NonNull 
 Stri

Store modules as set for faster contains()