package com.imyeyu.fx.ui.components;

import com.imyeyu.fx.icon.TimiFXIcon;
import com.imyeyu.fx.icon.TimiIcon;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.fx.utils.bg.BackgroundFillBuilder;
import com.imyeyu.fx.utils.scroll.SmoothScroll;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.utils.Collect;
import javafx.beans.binding.Bindings;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.skin.TextFieldSkin;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * {@link TimiFXIcon} 的图标选择器（标签搜索需要联网）
 *
 * @author 夜雨
 * @since 2022-08-01 16:08
 */
public class IconPicker extends TextField implements TimiFXUI {

	private final BorderPane root;

	/** 默认构造 */
	public IconPicker() {
		IconPickerPopup popup = new IconPickerPopup();

		// 注入面板
		root = new BorderPane();

		setEditable(false);

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

		// 更新选择
		textProperty().addListener((obs, o, value) -> {
			if (TimiJava.isEmpty(value)) {
				root.setLeft(null);
			} else {
				Text icon = TimiFXIcon.get(TimiIcon.valueOf(value));
				BorderPane.setMargin(icon, new Insets(0, 2, 0, 0));
				BorderPane.setAlignment(icon, Pos.CENTER);
				root.setLeft(icon);
			}
		});

		// 点击显示
		setOnMouseClicked(e -> {
			Bounds b = localToScreen(getLayoutBounds());
			popup.setX(b.getMinX() - 6); // 6 像素投影
			popup.setY(b.getMaxY() - 6 - 1);
			if (popup.getOwner() == null) {
				popup.initOwner(getScene().getWindow());
			}
			popup.show();
		});

		// 选择
		popup.group.selectedToggleProperty().addListener((obs, o, newToggle) -> {
			if (newToggle == null) {
				clear();
			} else if (newToggle instanceof ToggleIcon icon) {
				setText(icon.value.toString());
			}
		});
	}

	@Override
	protected Skin<?> createDefaultSkin() {
		Skin<?> skin = super.createDefaultSkin();
		if (skin instanceof TextFieldSkin textFieldSkin) {
			try {
				Pane textGroup = Ref.getFieldValue(textFieldSkin, "textGroup", Pane.class);

				root.setCenter(textGroup);

				textFieldSkin.getChildren().setAll(root);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}
		}
		return skin;
	}

	/**
	 * 获取选择的图标图像
	 *
	 * @return 图标图像
	 */
	public Image getValue() {
		return TimiFXIcon.getImage(TimiIcon.valueOf(getText()));
	}

	/**
	 * 图标选择弹窗
	 *
	 * @author 夜雨
	 * @since 2022-08-01 17:12
	 */
	private static class IconPickerPopup extends Stage {

		final ToggleGroup group;
		final List<ToggleIcon> icons;
		final Map<TimiIcon, String> unicodeMap = Arrays.stream(TimiIcon.values()).collect(Collectors.toMap(Function.identity(), TimiIcon::getUnicode));

		public IconPickerPopup() {
			// 图标
			TilePane tile = new TilePane();
			tile.setPadding(new Insets(6));

			icons = new ArrayList<>();
			group = new ToggleGroup();
			Map<TimiIcon, String> items = Collect.sortMap(unicodeMap, Comparator.comparing(Enum::name));
			for (Map.Entry<TimiIcon, String> item : items.entrySet()) {
				icons.add(new ToggleIcon(group, item.getKey()));
			}
			tile.getChildren().addAll(icons);
			focusedProperty().addListener((_, _, isFocused) -> {
				if (!isFocused) {
					hide();
				}
			});

			Scene scene = new Scene(new StackPane() {{
				setPadding(Shadow.PADDING);
				setBackground(BG.TRANSPARENT);
				getChildren().add(new BorderPane() {{
					setEffect(Shadow.POPUP);
					setBorder(Stroke.DEFAULT);
					setMaxHeight(280);
					setBackground(BG.DEFAULT);
					setCenter(new ScrollPane() {{
						setContent(tile);
						setPadding(new Insets(6, 8, 6, 8));
						setFitToWidth(true);

						SmoothScroll.pane.install(this);
					}});
				}});
			}});
			scene.setFill(null);
			TimiFXUI.applyStyle(scene);
			setScene(scene);
			setWidth(360);
			setHeight(240);
			initStyle(StageStyle.TRANSPARENT);
		}
	}

	/**
	 * 图标按钮
	 *
	 * @author 夜雨
	 * @since 2022-08-01 17:38
	 */
	private static class ToggleIcon extends ToggleButton {

		private static final Background SELECTED = BackgroundFillBuilder.solid("#99D1FF").build();

		/** 图标名称 */
		final TimiIcon value;

		public ToggleIcon(ToggleGroup ownerGroup, TimiIcon value) {
			super("");
			this.value = value;

			setGraphic(TimiFXIcon.get(value, 16));
			getStyleClass().clear();
			managedProperty().bind(visibleProperty());
			borderProperty().bind(Bindings.when(hoverProperty()).then(Stroke.FOCUSED).otherwise(Stroke.TP));
			backgroundProperty().bind(Bindings.when(selectedProperty()).then(SELECTED).otherwise(BG.TRANSPARENT));

			ownerGroup.getToggles().add(this);
		}

		@Override
		protected Skin<?> createDefaultSkin() {
			Skin<?> defaultSkin = super.createDefaultSkin();
			setPadding(new Insets(getFont().getSize() * .25));
			return defaultSkin;
		}
	}
}
