package cn.forevermc.launcher.ctrl.pane;

import cn.forevermc.launcher.bean.Config;
import cn.forevermc.launcher.bean.Game;
import cn.forevermc.launcher.bean.LaunchGame;
import cn.forevermc.launcher.bean.MCPopupTips;
import cn.forevermc.launcher.bean.Page;
import cn.forevermc.launcher.core.Launcher;
import cn.forevermc.launcher.service.BGService;
import cn.forevermc.launcher.service.FMCLoginService;
import cn.forevermc.launcher.service.GameService;
import cn.forevermc.launcher.service.MCPopupTipsService;
import cn.forevermc.launcher.service.PageService;
import cn.forevermc.launcher.service.SplashService;
import cn.forevermc.launcher.util.FabricBuilder;
import cn.forevermc.launcher.util.Resources;
import cn.forevermc.launcher.view.pages.MenuPane;
import com.sun.javafx.scene.control.skin.Utils;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.beans.binding.Bindings;
import javafx.geometry.VPos;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.fx.task.RunAsync;
import com.imyeyu.fx.ui.MinecraftFont;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.inject.annotation.Controller;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
import com.imyeyu.inject.annotation.SuperInject;
import com.imyeyu.java.TimiJava;
import com.imyeyu.network.Network;

/**
 * 菜单
 *
 * @author 夜雨
 * @since 2022-11-22 00:27
 */
@Slf4j
@Controller
@SuperInject
public class Menu extends MenuPane {

	@Inject
	private Config config;

	@Inject
	private Stage stage;

	@Inject
	private Dialog dialog;

	@Inject
	private Launcher launcher;

	@Inject
	private BGService bgService;

	@Inject
	private GameOption gameOption;

	@Inject
	private GameService gameService;

	@Inject
	private PageService pageService;

	@Inject
	private LaunchGame launchGame;

	@Inject
	private FMCLoginService fmcLoginService;

	@Inject
	private SplashService splashService;

	@Inject
	private MCPopupTipsService mcPopupTipsService;

	private final AutoLaunchService autoLaunchService;

	public Menu() {
		autoLaunchService = new AutoLaunchService();

		// 闪烁标语
		GraphicsContext g = splashCanvas.getGraphicsContext2D();
		g.setFill(Colorful.YELLOW);
		g.setFont(MinecraftFont.X32());
		g.setEffect(new DropShadow(0, 1, 1, Color.BLACK));
		g.setTextBaseline(VPos.TOP);
		splashCanvas.widthProperty().bind(Bindings.createDoubleBinding(() -> {
			if (splash.isEmpty().get()) {
				return 1D;
			}
			return Utils.computeTextWidth(g.getFont(), splash.get(), -1);
		}, splash));
		ScaleTransition transition = new ScaleTransition(Duration.millis(300), splashCanvas);
		transition.setFromX(.9);
		transition.setFromY(.9);
		transition.setToX(1);
		transition.setToY(1);
		transition.setCycleCount(Timeline.INDEFINITE);
		transition.setAutoReverse(true);
		transition.play();

		// 账号管理
		fmcAccount.visibleProperty().bind(loginTypeSelector.valueProperty().isEqualTo(Game.Option.LoginType.FOREVER_MC));
		fmcAccount.setOnAction(e -> Network.openURIInBrowser("https://space.imyeyu.net"));

		// 服务器状态
		fmcServer.visibleProperty().bind(loginTypeSelector.valueProperty().isEqualTo(Game.Option.LoginType.FOREVER_MC));

		// 启动版本管理
		launchGameSelect.setOnAction(e -> pageService.to(Page.GAME_SELECT));

		// 启动
		launch.setOnAction(e -> {
			if (autoLaunchService.isRunning()) {
				autoLaunchService.isCancel = true;
				return;
			}
			// 安装 Fabric
			if (loginTypeSelector.isOnline() && launchGame.isSupportFMCLogin() && !launchGame.isFabric()) {
				dialog.setContent(TimiFXUI.MULTILINGUAL.text("fmc.launcher.pack_option.fabric.installing"));
				dialog.eject();

				new FabricBuilder() {

					{
						setBuildGame(launchGame.get());
					}

					@Override
					protected void onFinish(Game builedGame) {
						launchGame.set(builedGame);
						// TODO 应该自动设置？
						config.getLauncher().getGame().set(builedGame.getName());
						loginTypeSelector.setValue(Game.Option.LoginType.FOREVER_MC);
						launcher.launch();
					}

					@Override
					protected void onException(Throwable e) {
						dialog.setContent(e.getMessage());
						dialog.setCloseEvent(() -> pageService.to(Page.MENU));
						dialog.eject();
						log.error("fabric install error", e);
					}
				}.start();
				return;
			}
			// 启动
			launcher.launch();
		});
		launch.getLabel().textProperty().bind(Bindings.createStringBinding(() -> {
			if (!autoLaunchService.isCancel && autoLaunchService.isRunning()) {
				if (launch.isHover()) {
					return TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.launch.auto.cancel");
				} else {
					return TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.launch.auto", autoLaunchService.getValue());
				}
			} else {
				return TimiFXUI.MULTILINGUAL.text("launch");
			}
		}, autoLaunchService.valueProperty(), autoLaunchService.stateProperty(), launch.hoverProperty()));

		// 语言
		langSelect.setOnAction(e -> pageService.to(Page.LANG_SELECT));

		// 设置
		super.option.setOnAction(e -> pageService.to(Page.OPTION));

		// 退出
		exit.setOnAction(e -> stage.close());

		// 关于
		super.about.setOnAction(e -> pageService.to(Page.ABOUT));
	}

	@InvokeForInjected
	private void config() {
		name.textProperty().bindBidirectional(config.getPlayer().getName());
		password.textProperty().bindBidirectional(config.getPlayer().getPassword());
	}

	@InvokeForInjected
	private void injected() {
		// 闪烁标语
		splashService.valueProperty().addListener((obs, o, newText) -> {
			GraphicsContext g = splashCanvas.getGraphicsContext2D();
			g.clearRect(0, 0, splashCanvas.getWidth(), splashCanvas.getHeight());
			g.fillText(newText, 0, 0);
		});
		// 动态标题
		title.imageProperty().bind(Bindings.when(launchGame.newTitleProperty()).then(Resources.TITLE_NEW).otherwise(Resources.TITLE));
		// 账号管理
		mcPopupTipsService.install(fmcAccount, TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.account"));
		// 账号验证方式
		launchGame.addListener((obs, oldGame, newGame) -> {
			// 配置绑定
			if (oldGame != null && oldGame.getOption().getLoginType().isBound()) {
				oldGame.getOption().getLoginType().unbind();
			}
			loginTypeSelector.setValue(newGame.getOption().getLoginType().get());
			newGame.getOption().getLoginType().bind(loginTypeSelector.valueProperty());
		});
		// 必须离线启动
		loginTypeSelector.requiredOfflineProperty().bind(launchGame.supportFMCLoginProperty().not());
		// 账号验证方式提示
		MCPopupTips loginTypeTips = new MCPopupTips();
		loginTypeTips.enableProperty().bind(loginTypeTips.getNode().textProperty().isNotEmpty());
		loginTypeTips.getNode().setWrapText(true);
		loginTypeTips.getNode().setMaxWidth(280);
		loginTypeTips.getNode().textProperty().bind(Bindings.createStringBinding(() -> loginTypeSelector.getValue().getTips(), launchGame, loginTypeSelector.valueProperty()));
		mcPopupTipsService.install(loginTypeSelector, loginTypeTips);
		// 启动版本
		launchGameLabel.textProperty().bind(Bindings.createStringBinding(() -> {
			Game launchGame = this.launchGame.get();
			if (launchGame == null) {
				return TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.launch.pack", TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.launch.pack.null"));
			}
			// 版本名称
			String gameName = launchGame.getOption().getName().get();
			if (TimiJava.isEmpty(gameName)) {
				return TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.launch.pack", launchGame.getName());
			}
			return TimiFXUI.MULTILINGUAL.textArgs("fmc.launcher.menu.launch.pack", gameName);
		}, launchGame));
		// 服务器状态
		mcPopupTipsService.install(fmcServer, TimiFXUI.MULTILINGUAL.text("server.status"));
		// 启动版本管理
		mcPopupTipsService.install(launchGameSelect, TimiFXUI.MULTILINGUAL.text("fmc.launcher.menu.launch.pack.list"));
		// 获取标语
		splash.bind(splashService.valueProperty());
	}

	@Override
	public void onShow() {
		super.onShow();
		// 离线
		if (launchGame.isNotSupportFMCLogin()) {
			loginTypeSelector.setValue(Game.Option.LoginType.OFFLINE);
		}
		// 自动启动
		if (isFirstShow && config.getLauncher().getAutoStartup().get()) {
			autoLaunchService.start();
		}
	}

	/**
	 * 自启服务
	 *
	 * @author 夜雨
 * @since 2022-12-03 20:18
	 */
	private class AutoLaunchService extends RunAsync<Integer> {

		/** true 为取消 */
		boolean isCancel = false;

		@Override
		protected Integer call() throws Exception {
			int i = 8;
			while (0 < i) {
				update(i--);
				if (isCancel) {
					break;
				}
				Thread.sleep(1000);
			}
			return 0;
		}

		@Override
		protected void onFinish() {
			if (!isCancel) {
				launcher.launch();
			}
		}
	}
}
