package cn.forevermc.launcher.bean;

import com.google.gson.JsonObject;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.StringProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.java.TimiJava;

import java.io.File;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 游戏
 *
 * @author 夜雨
 * @since 2021-11-26 11:13
 */
@Data
public class Game {

	/**
	 * 游戏版本类型
	 *
	 * @author 夜雨
	 * @since 2022-11-21 14:54
	 */
	public enum Type {

		/** 快照 */
		SNAPSHOT,

		/** 正式版 */
		RELEASE,

		/** 旧的测试版 */
		OLD_BETA,

		/** 旧的实验版 */
		OLD_ALPHA
	}

	// ---------- 版本属性，这些属性在解析前就有效 ----------

	/** 显示名称 */
	private String name;

	/** 版本路径（如：.minecraft/versions/1.20） */
	private File path;

	/** JAR 文件 */
	private File jar;

	/** JSON 文件 */
	private File json;

	/** yaml 文件（ForeverMC 针对此整合包的配置） */
	private File yaml;

	/** JSON 文件的根节点 */
	private JsonObject jsonRoot;

	/** 发布时间 */
	private Long releaseAt;

	/** true 为原版 */
	private boolean isOriginal;

	/** true 为 Fabric 版本 */
	private boolean isFabric;

	/** true 为上古版本 */
	private boolean isLegacy;

	/** 版本设置 */
	private Option option;

	// ---------- 版本 JSON 数据，这些属性在解析后才有效 ----------

	/** ID（版本号，可能会被修改） */
	private String id;

	/** 游戏版本类型 */
	private Type type;

	/** 元数据 URL */
	private String url;

	/** 版本元数据 */
	private MetaData metaData;

	@Override
	public boolean equals(Object object) {
		if (this == object) return true;
		if (object == null || getClass() != object.getClass()) return false;

		Game game = (Game) object;
		return Objects.equals(path, game.path);
	}

	@Override
	public int hashCode() {
		int result = name != null ? name.hashCode() : 0;
		result = 31 * result + (path != null ? path.hashCode() : 0);
		return result;
	}

	/**
	 * 版本元数据，通过 {@link cn.forevermc.launcher.service.GameService#readMetaData(Game)} 解析后有效
	 *
	 * @author 夜雨
	 * @since 2022-11-21 11:28
	 */
	@Data
	public static class MetaData {

		/**
		 * 真实版本号，目前仅在正式版有效
		 *
		 * @author 夜雨
		 * @since 2023-06-17 16:11
		 */
		@Getter
		public static class RealVersion {

			/** 版本号匹配正则 */
			private static final Pattern PATTERN = Pattern.compile("(\\d)\\.(\\d+)\\.?(\\d+)?");

			/** 版本号 */
			private String value;

			/** 根版本 */
			private int root = 0;

			/** 主版本 */
			private int main = 0;

			/** BUG 修正版本 */
			private int bug = 0;

			/**
			 * 设置版本号，通过此方法自动解析详细版本号
			 *
			 * @param value 版本号
			 */
			public void setValue(String value) {
				this.value = value;
				Matcher matcher = PATTERN.matcher(value);
				if (matcher.find()) {
					root = Integer.parseInt(matcher.group(1));
					main = Integer.parseInt(matcher.group(2));
					if (TimiJava.isNotEmpty(matcher.group(3))) {
						bug = Integer.parseInt(matcher.group(3));
					}
				}
			}

			/** @return true 为支持 Fabric */
			public boolean isSupportFabric() {
				return main < 14;
			}

			/** @return true 为更现代的样式 */
			public boolean isModernStyle() {
				return 19 < main;
			}
		}

		/** 版本号（可能因模组加载器而改变） */
		private String version;

		/** 真实的 Minecraft 版本号 */
		private RealVersion realVersion;

		/** 标题 */
		private String title;

		/** 启动类 */
		private String mainClass;

		/** 需要 Java 版本 */
		private String javaVersion;

		/** 游戏参数模板 */
		private String argsGame;

		/** JVM 参数模板 */
		private String argsJVM;

		/** 启动核心地址 */
		private String coreURL;

		/** 启动核心 SHA1 */
		private String coreSHA1;

		/** 核心大小 */
		private Long coreSize;

		/** 资源版本 */
		private String assetsVersion;

		/** 资源列表 */
		private List<Assets> assetList;

		/** 依赖列表 */
		private List<Libraries> librarieList;

		/** 需下载的文件列表（解析结果，包括资源和依赖文件） */
		private List<FileDownload> downloadList;

		/**
		 * 资源
		 *
		 * @author 夜雨
		 * @since 2022-11-21 11:04
		 */
		@Data
		public static class Assets {

			/** 哈希值 */
			private String hash;

			/** 下载 URL */
			private String url;

			/** 大小 */
			private Long size;
		}

		/**
		 * 依赖
		 *
		 * @author 夜雨
		 * @since 2022-11-21 11:04
		 */
		@Data
		public static class Libraries {

			/** 哈希值 */
			private String sha1;

			/** 相对路径 */
			private String path;

			/** 下载 URL */
			private String url;

			/** 文件大小 */
			private Long size;

			/** true 为 JNA 依赖 */
			private boolean isNatives;

			/** @return true 为非 JNA 依赖 */
			public boolean isNotNatives() {
				return !isNatives;
			}
		}
	}

	/**
	 * 版本设置
	 *
	 * @author 夜雨
	 * @since 2022-12-09 20:31
	 */
	@Data
	public static class Option implements Serializable {

		/**
		 * 登录方式
		 *
		 * @author 夜雨
		 * @since 2022-12-05 23:05
		 */
		@Getter
		@AllArgsConstructor
		public enum LoginType implements Serializable {

			/** 离线 */
			OFFLINE(TimiFXUI.MULTILINGUAL.text("offline"), TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.account.type", TimiFXUI.MULTILINGUAL.text("offline"))),

			/** ForeverMC */
			FOREVER_MC("ForeverMC", TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.account.type", TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.account.fmc"))),

			/** 官方正版验证（未支持） */
			MOJANG("Mojang", TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.account.type", TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.account.mojang")));

			/** 显示名称 */
			final String name;

			/** 提示 */
			final String tips;
		}

		/**
		 * 可选规则
		 *
		 * @author 夜雨
		 * @since 2023-06-17 11:34
		 */
		@Getter
		@AllArgsConstructor
		public enum Rules {

			/** 体验模式 */
			DEMO("is_demo_user"),

			/** 自定义尺寸 */
			CUSTOM_RESOLUTION("has_custom_resolution"),

			/** 快速游戏日志 */
			QUICK_PLAYS_SUPPORT("has_quick_plays_support"),

			/** 快速单人游戏 */
			QUICK_PLAY_SINGLEPLAYER("is_quick_play_singleplayer"),

			/** 快速多人游戏 */
			QUICK_PLAY_MULTIPLAYER("is_quick_play_multiplayer"),

			/** 快速领域游戏 */
			QUICK_PLAY_REALMS("is_quick_play_realms");

			/** 名称 */
			final String name;
		}

		/** 名称，从整合版版本包获取并储存 */
		private StringProperty name;

		/** 支持的登录方式 */
		private ObjectProperty<LoginType> loginType;

		/** 启动 Java */
		private StringProperty java;

		/** 服务器 */
		private StringProperty server;

		/** 是否自动连接 */
		private BooleanProperty autoConnect;
	}
}
