package cn.forevermc.launcher.service;

import cn.forevermc.launcher.bean.APISetting;
import cn.forevermc.launcher.util.Resources;
import com.google.gson.Gson;
import com.imyeyu.fx.listener.NewValueListener;
import com.imyeyu.fx.task.RunAsyncDaemon;
import com.imyeyu.fx.utils.BgImage;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
import com.imyeyu.inject.annotation.Service;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.FileRequest;
import com.imyeyu.utils.OS;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import lombok.extern.slf4j.Slf4j;

import javax.naming.NoPermissionException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

/**
 * 动态背景地址获取服务
 *
 * @author 夜雨
 * @since 2022-11-28 00:12
 */
@Slf4j
@Service
public class BGService implements OS.FileSystem {

	private static final String CACHE_PATH = "etc" + SEP + "bg";

	@Inject
	private APISettingService apiSettingService;

	@Inject
	private Gson gson;

	private final ObjectProperty<Background> value;

	public BGService() {
		value = new SimpleObjectProperty<>();
	}

	@InvokeForInjected
	private void injected() {
		new RunAsyncDaemon<InputStream>(3000)  {

			private final Object lock = new Object();

			private APISetting.DynamicList bgList = null;

			@Override
			protected InputStream call() throws Exception {
				if (apiSettingService.getValue() == null) {
					apiSettingService.valueProperty().addListener((NewValueListener<APISetting>) apiSetting -> {
						bgList = apiSetting.getBg();
						synchronized (lock) {
							lock.notifyAll();
						}
					});
					// 等待配置
					log.info("waiting apiSetting");
					synchronized (lock) {
						lock.wait(2000);
					}
					TimiException.required(bgList, "not found bgList");
				} else {
					bgList = apiSettingService.getValue().getBg();
				}
				List<File> fileList = IO.listFile(IO.dir(CACHE_PATH));
				for (File file : fileList) {
					if (!bgList.getList().contains(file.getName())) {
						// 删除过时的背景
						log.info("delete bg {}", file.getName());
						IO.destroy(file);
					}
				}
				for (String item : bgList.getList()) {
					IO.file(IO.fitPath(CACHE_PATH) + item, newFile -> {
						// 下载新的背景
						try {
							log.info("download new bg {}", item);
							FileRequest.get(Resources.TIMI_SERVER_API + "/attachment/download/" + item).toFile(newFile);
						} catch (IOException | NoPermissionException e) {
							throw new RuntimeException(e);
						}
					});
				}
				String result = bgList.getPermanent(); // 常驻背景
				if (TimiJava.isEmpty(result)) {
					// 随机背景
					Collections.shuffle(bgList.getList());
					result = bgList.getList().getFirst();
				}
				return IO.getInputStream(IO.fitPath(CACHE_PATH) + result);
			}

			@Override
			protected void onFinish(InputStream stream) {
				if (!isTimeout) {
					setValue(stream);
				}
			}

			@Override
			protected void onException(Throwable e) {
				log.error("BGService", e);
			}

			@Override
			protected void onTimeout() {
				// 内置背景
				setValue(IO.resourceToInputStream(getClass(), "assets/img/bg.png"));
			}

			private void setValue(InputStream stream) {
				value.set(new BgImage(new Image(stream, -1, -1, false, false)).cover().build());
			}
		}.start();
	}

	public ReadOnlyObjectProperty<Background> valueProperty() {
		return value;
	}

	public Background getValue() {
		return value.get();
	}
}
