package com.imyeyu.fx.ui.components;

import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.fx.utils.Nodes;
import com.imyeyu.fx.utils.bg.BackgroundFillBuilder;
import com.imyeyu.java.TimiJava;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Skin;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;

/**
 * 图标选择状态按钮，可选图片、SVG 路径或 {@link com.imyeyu.fx.icon.TimiFXIcon} 的字体图标
 *
 * @author 夜雨
 * @since 2022-05-18 10:16
 */
public class ToggleIcon extends ToggleButton implements TimiFXUI {

	private static final String STYLE_CLASS = "toggle-icon";
	private static final Background BG_SELECTED = BackgroundFillBuilder.solid("#99D1FF").build();

	/** 选中图标 */
	protected final Node selected;

	/** 非选中图标 */
	protected final Node otherwise;

	/** 是否自适应尺寸 */
	protected final BooleanProperty autoSize;

	private Insets iconPadding, iconTextPadding; // 缓存单独图标内边距和图标文本混合的内边距

	// ---------- 图片图标 ----------

	/**
	 * 构造图片图标选择按钮
	 *
	 * @param img 图片
	 */
	public ToggleIcon(Image img) {
		this(img, img);
	}

	/**
	 * 构造图片图标切换按钮
	 *
	 * @param selectedImg  已选图片
	 * @param otherwiseImg 未选图片
	 */
	public ToggleIcon(Image selectedImg, Image otherwiseImg) {
		this(new ImageView(selectedImg), new ImageView(otherwiseImg));
	}

	// ---------- SVG 图标 ----------

	/**
	 * 构造 SVG 图标选择按钮
	 *
	 * @param svg SVG 路径
	 */
	public ToggleIcon(String svg) {
		this(new SVGIcon(svg));
	}

	/**
	 * 构造 SVG 图标选择按钮
	 *
	 * @param selectedSVG  已选 SVG 路径
	 * @param otherwiseSVG 未选 SVG 路径
	 */
	public ToggleIcon(String selectedSVG, String otherwiseSVG) {
		this(new SVGIcon(selectedSVG), new SVGIcon(otherwiseSVG));
	}

	/**
	 * 构造 SVG 图标选择按钮
	 *
	 * @param icon SVG 图标
	 */
	public ToggleIcon(SVGIcon icon) {
		this(icon, icon);
	}

	// ---------- 默认构造 ----------

	/**
	 * 构造自定义节点选择按钮
	 *
	 * @param icon 节点
	 */
	public ToggleIcon(Node icon) {
		this(icon, icon);
	}

	/**
	 * 构造 SVG 图标选择按钮
	 *
	 * @param selected  已选节点
	 * @param otherwise 未选节点
	 */
	public ToggleIcon(Node selected, Node otherwise) {
		this.selected = selected;
		this.otherwise = otherwise;
		autoSize = new SimpleBooleanProperty(false);

		if (selected == otherwise) {
			setGraphic(selected);
		} else {
			otherwise.getStyleClass().add("icon");
			graphicProperty().bind(Bindings.when(selectedProperty()).then(selected).otherwise(otherwise));
		}
		selected.getStyleClass().add("icon");
		Nodes.bindHoverOpacity(this);

		getStyleClass().setAll(CSS.MINECRAFT, STYLE_CLASS);
		setAlignment(Pos.CENTER);
		setMaxHeight(Double.MAX_VALUE);
		backgroundProperty().bind(Bindings.when(selectedProperty()).then(BG_SELECTED).otherwise(BG.TRANSPARENT));

		// 自适应尺寸、单独图标、图标文本混合时设置不同的内边距
		paddingProperty().bind(Bindings.createObjectBinding(() -> {
			if (autoSize.get()) {
				return Insets.EMPTY;
			} else {
				if (TimiJava.isEmpty(getText())) {
					return iconPadding == null ? Insets.EMPTY : iconPadding;
				} else {
					return iconTextPadding == null ? Insets.EMPTY : iconTextPadding;
				}
			}
		}, textProperty(), autoSize, skinProperty()));
	}

	@Override
	public String getUserAgentStylesheet() {
		return ToggleIcon.class.getResource(RESOURCE + "style/components/toggle-icon.css").toExternalForm();
	}

	/**
	 * 添加按钮背景
	 *
	 * @return 本实例
	 */
	public ToggleIcon withBackground() {
		return withBackground(null);
	}

	/**
	 * 添加按钮背景
	 *
	 * @param borderClass 边框类
	 * @return 本实例
	 */
	public ToggleIcon withBackground(String borderClass) {
		getStyleClass().add(CSS.BG_BUTTON);
		if (TimiJava.isNotEmpty(borderClass)) {
			getStyleClass().add(borderClass);
		}
		setAlignment(Pos.CENTER);

		backgroundProperty().unbind();
		return this;
	}

	/**
	 * 自适应尺寸，不使用内边距填充，图标尺寸决定组件尺寸
	 *
	 * @return 本实例
	 */
	public ToggleIcon autoSize() {
		autoSize.set(true);
		return this;
	}

	/**
	 * 获取当前是否自适应尺寸，ture 时图标尺寸决定组件尺寸
	 *
	 * @return true 为自适应尺寸
	 */
	public boolean isAutoSize() {
		return autoSize.get();
	}

	/**
	 * 设置是否自适应尺寸，ture 时图标尺寸决定组件尺寸
	 *
	 * @param autoSize true 为自适应尺寸
	 */
	public void setAutoSize(boolean autoSize) {
		this.autoSize.set(autoSize);
	}

	/**
	 * 获取自适应尺寸监听
	 *
	 * @return 自适应尺寸监听
	 */
	public BooleanProperty autoSizeProperty() {
		return autoSize;
	}

	@Override
	protected Skin<?> createDefaultSkin() {
		Skin<?> defaultSkin = super.createDefaultSkin();
		double h = getFont().getSize() * .382;
		double v = h * .8;
		double tv = h * .6;
		iconPadding = new Insets(v);
		iconTextPadding = new Insets(tv, h, tv, h);
		return defaultSkin;
	}
}
