package com.imyeyu.fx.ui.components.alert;

import com.imyeyu.fx.icon.TimiFXIcon;
import com.imyeyu.fx.icon.TimiIcon;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.fx.ui.components.FileTreeView;
import com.imyeyu.fx.ui.components.IconButton;
import com.imyeyu.fx.ui.components.ToggleIcon;
import com.imyeyu.fx.ui.components.popup.PopupTipsService;
import com.imyeyu.fx.ui.components.popup.tips.PopupTipsLabel;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArgReturn;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import lombok.Getter;
import lombok.Setter;

import java.io.File;
import java.util.List;

/**
 * 抽象文件选择器，基本文件选择窗体
 *
 * @author 夜雨
 * @since 2022-05-23 15:34
 */
public abstract class AbstractAlertFile extends AbstractAlert implements TimiFXUI {


	/** 当前绝对路径 */
	protected final TextField absolutePath;

	/** 切换隐藏 */
	protected final ToggleIcon toggleHide;

	/** 确认按钮 */
	protected final AlertButton confirm;

	/** 取消按钮 */
	protected final AlertButton cancel;

	/** 文件目录树 */
	@Getter
	protected final FileTreeView tree;

	/** 确认事件，返回 true 自动关闭窗体 */
	@Setter
	@Getter
	private CallbackArgReturn<List<File>, Boolean> onConfirmEvent;

	/**
	 * 默认构造器
	 *
	 * @param mode 模式
	 */
	public AbstractAlertFile(SelectionMode mode) {
		VBox header = new VBox();

		// 主页
		IconButton home = new IconButton(TimiFXIcon.get(TimiIcon.HOME));
		PopupTipsService.installText(home, TimiFXUI.MULTILINGUAL.text("home"));

		// 刷新
		IconButton refresh = new IconButton(TimiFXIcon.get(TimiIcon.REFRESH));
		PopupTipsService.installText(refresh, TimiFXUI.MULTILINGUAL.text("refresh"));

		// 创建文件夹
		IconButton mkdir = new IconButton(TimiFXIcon.get(TimiIcon.FOLDER_ADD));
		PopupTipsService.installText(mkdir, TimiFXUI.MULTILINGUAL.text("file.mkdir"));

		// 删除
		IconButton destroy = new IconButton(TimiFXIcon.get(TimiIcon.FAIL, Colorful.RED));
		PopupTipsService.installText(destroy, TimiFXUI.MULTILINGUAL.text("delete"));

		// 切换隐藏
		toggleHide = new ToggleIcon(TimiFXIcon.get(TimiIcon.HIDE));
		PopupTipsService.installText(toggleHide, TimiFXUI.MULTILINGUAL.text("file.show_hide"));

		BorderPane ctrl = new BorderPane();
		ctrl.setLeft(new HBox(home, refresh, mkdir, destroy));
		ctrl.setRight(toggleHide);
		header.getChildren().add(ctrl);

		BorderPane absolutePathPane = new BorderPane();
		absolutePathPane.setBorder(Stroke.TOP);

		// 绝对路径
		absolutePath = new TextField();
		absolutePath.setBorder(Border.EMPTY);
		IconButton absolutePathGo = new IconButton(TimiFXIcon.get(TimiIcon.ARROW_2_E));
		{
			if (mode == SelectionMode.SINGLE) {
				PopupTipsLabel tips = PopupTipsService.installBindingText(absolutePath, absolutePath.textProperty());
				tips.enableProperty().bind(absolutePath.textProperty().isNotEmpty());
			} else {
				absolutePathPane.setVisible(false);
				absolutePathPane.setManaged(false);
			}

			absolutePathPane.setCenter(absolutePath);
			absolutePathPane.setRight(absolutePathGo);
		}
		header.getChildren().add(absolutePathPane);

		// 目录树
		tree = new FileTreeView();
		tree.setBorder(Stroke.TOP);
		tree.getSelectionModel().setSelectionMode(mode);

		root.setTop(header);
		root.setCenter(tree);

		btnPane.setBorder(Stroke.TOP);

		{
			confirm = AlertButton.confirm();
			confirm.setBorder(Stroke.LEFT);

			cancel = AlertButton.cancel();
			cancel.setBorder(Stroke.LEFT);

			setRightButtons(confirm, cancel);
			btnPane.setPadding(Insets.EMPTY);
			rightButtons.setSpacing(0);
		}

		setEnableSizeToScene(false);
		setWidth(390);
		setHeight(490);

		// ---------- 事件 ----------

		// 根目录
		home.setOnAction(e -> {
			tree.getSelectionModel().clearAndSelect(0);
			tree.scrollTo(0);
		});

		// 刷新
		refresh.disableProperty().bind(Bindings.createBooleanBinding(() -> {
			List<TreeItem<File>> items = tree.getSelectionModel().getSelectedItems();
			// 没有选择、多选、选的不是文件时禁用
			return items == null || items.size() != 1 || items.get(0).getValue().isFile();
		}, tree.getSelectionModel().selectedItemProperty()));
		refresh.setOnAction(e -> tree.refreshItem(tree.getSelectionModel().getSelectedItem()));

		// 创建文件夹
		mkdir.disableProperty().bind(refresh.disableProperty());
		mkdir.setOnAction(e -> tree.mkdir(tree.getSelectionModel().getSelectedItem()));

		// 删除
		List<File> roots = List.of(File.listRoots());
		destroy.disableProperty().bind(Bindings.createBooleanBinding(() -> {
			ObservableList<TreeItem<File>> items = tree.getSelectionModel().getSelectedItems();
			if (items.isEmpty()) {
				return true;
			}
			for (TreeItem<File> item : items) {
				if (roots.contains(item.getValue())) {
					return true;
				}
			}
			return false;
		}, tree.getSelectionModel().getSelectedItems()));
		destroy.setOnAction(e -> tree.destroy(tree.getSelectionModel().getSelectedItems()));

		// 显示隐藏
		toggleHide.selectedProperty().bindBidirectional(tree.showHideProperty());
		toggleHide.setOnAction(e -> tree.getRoots().forEach(i -> i.setExpanded(false)));

		// 前往路径
		absolutePathGo.setOnAction(e -> {
			if (TimiJava.isNotEmpty(absolutePath.getText())) {
				File file = new File(absolutePath.getText());
				if (file.exists()) {
					tree.selectItem(file);
				} else {
					AlertTips.error(this, TimiFXUI.MULTILINGUAL.text("file.tips.not_found_target"));
				}
			}
		});

		// 选中
		tree.getSelectionModel().selectedItemProperty().addListener((obs, o, newItem) -> {
			if (newItem != null && newItem.getValue() != null) {
				absolutePath.setText(newItem.getValue().getAbsolutePath());
			}
		});

		// 双击触发确认
		tree.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
			if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2) {
				confirm.fire();
			}
		});

		// 确认
		confirm.setOnAction(e -> {
			if (onConfirmEvent != null) {
				List<File> list = tree.getSelectionModel().getSelectedItems().stream().map(TreeItem::getValue).toList();
				if (onConfirmEvent.handler(list)) {
					close();
				}
			} else {
				close();
			}
		});
	}

	/**
	 * 添加构建节点过滤器，返回 false 时不创建该节点
	 *
	 * @param itemFilter 节点过滤器
	 */
	public void addItemFilter(CallbackArgReturn<File, Boolean> itemFilter) {
		tree.addItemFilter(itemFilter);
	}

	/**
	 * 移除构建节点过滤器
	 *
	 * @param itemFilter 节点过滤器
	 */
	public void removeItemFilter(CallbackArgReturn<File, Boolean> itemFilter) {
		tree.removeItemFilter(itemFilter);
	}

	/**
	 * 异步选择目标目录
	 *
	 * @param path 目标目录
	 */
	public void selectItem(String path) {
		tree.selectItem(path);
	}

	/**
	 * 异步选择目标文件
	 *
	 * @param file 目标文件
	 */
	public void selectItem(File file) {
		tree.selectItem(file);
	}

	/**
	 * 获取是否显示隐藏文件
	 *
	 * @param showHide true 为显示隐藏文件
	 */
	public void isShowHide(boolean showHide) {
		toggleHide.setSelected(showHide);
	}

	/**
	 * 设置是否显示隐藏文件
	 *
	 * @param showHide true 为显示隐藏文件
	 */
	public void setShowHide(boolean showHide) {
		toggleHide.setSelected(showHide);
	}

	/**
	 * 获取切换显示隐藏文件监听
	 *
	 * @return 切换显示隐藏文件监听
	 */
	public BooleanProperty showHideProperty() {
		return toggleHide.selectedProperty();
	}
}
