package top.octopusyan.base;

import com.jfoenix.controls.JFXButton;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import top.octopusyan.http.EasyHttp;
import top.octopusyan.manager.FrpManager;
import top.octopusyan.model.ApplicatonStore;
import top.octopusyan.utils.FxmlUtil;
import top.octopusyan.utils.Loading;
import top.octopusyan.utils.TooltipUtil;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

/**
 * @author : octopus yan
 * @email : octopus_yan@foxmail.com
 * @description : 通用视图控制器
 * @create : 2022-3-31 18:09
 */
public abstract class BaseController<P extends Pane> implements Initializable {

    private Application application;

    private double xOffSet = 0, yOffSet = 0;

    private volatile Loading loading;

    protected TooltipUtil tooltipUtil;

    public void jumpTo(BaseController<P> controller) throws IOException {
        FXMLLoader fxmlLoader = FxmlUtil.init(controller.getRootFxmlPath());

        Scene scene = getRootPanel().getScene();
        double oldHeight = getRootPanel().getPrefHeight();
        double oldWidth = getRootPanel().getPrefWidth();

        Pane root = fxmlLoader.load();
        Stage stage = (Stage) scene.getWindow();
        // 窗口大小
        double newWidth = root.getPrefWidth() + 20;
        double newHeight = root.getPrefHeight() + 20;
        // 窗口位置
        double newX = stage.getX() - (newWidth - oldWidth) / 2;
        double newY = stage.getY() - (newHeight - oldHeight) / 2;
        scene.setRoot(root);
        stage.setX(newX < 0 ? 0 : newX);
        stage.setY(newY < 0 ? 0 : newY);
        stage.setWidth(newWidth);
        stage.setHeight(newHeight);

        controller = fxmlLoader.getController();
        controller.setApplication(getApplication());
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 全局窗口拖拽
        if (dragWindow()) {
            // 窗口拖拽
            getRootPanel().setOnMousePressed(event -> {
                xOffSet = event.getSceneX();
                yOffSet = event.getSceneY();
            });
            getRootPanel().setOnMouseDragged(event -> {
                Stage stage = (Stage) getRootPanel().getScene().getWindow();
                stage.setX(event.getScreenX() - xOffSet);
                stage.setY(event.getScreenY() - yOffSet);
            });
        }

        // app 版本信息
        if (getAppVersionLabel() != null) getAppVersionLabel().setText("v" + ApplicatonStore.APP_VERSION);

        // 这个位置的左边第一个 JFXBtn 会莫名其妙会的焦点效果，启动时禁用焦点，取消按钮效果
        if (getFirstBtn() != null) getFirstBtn().setDisableVisualFocus(true);

        // 最小化窗口
        if (getMinimizeBtn() != null) getMinimizeBtn().setOnMouseClicked(event -> {
            if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1) {
                Stage stage = (Stage) getRootPanel().getScene().getWindow();
                stage.setIconified(true);
            }
        });

        // 关闭窗口
        if (getClooseBtn() != null) getClooseBtn().setOnMouseClicked(event -> {
            if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1) {
                onDestroy();
            }
        });

        // 初始化数据
        initData();

        // 初始化视图样式
        initViewStyle();

        // 初始化视图事件
        initViewAction();
    }

    public void showLoading() {
        showLoading(null);
    }

    public void showLoading(String message) {
        if (loading == null) loading = new Loading((Stage) getRootPanel().getScene().getWindow());
        if (StringUtils.isNotEmpty(message)) loading.showMessage(message);
        loading.show();
    }

    public void setApplication(Application application) {
        this.application = application;
    }

    public Application getApplication() {
        return application;
    }

    public boolean isLoadShowing() {
        return loading != null && loading.showing();
    }

    public void stopLoading() {
        loading.closeStage();
    }

    protected TooltipUtil getTooltipUtil() {
        if (tooltipUtil == null) tooltipUtil = TooltipUtil.getInstance(getRootPanel());
        return tooltipUtil;
    }

    /**
     * 窗口拖拽设置
     *
     * @return 是否启用
     */
    public abstract boolean dragWindow();

    /**
     * 获取根布局
     *
     * @return 根布局对象
     */
    public abstract P getRootPanel();

    /**
     * 获取根布局
     *
     * @return 根布局对象
     */
    @NotNull
    public abstract String getRootFxmlPath();

    /**
     * App版本信息标签
     */
    public abstract Label getAppVersionLabel();

    /**
     * 关闭按钮
     */
    public abstract Button getClooseBtn();

    /**
     * 最小化按钮
     */
    public abstract Button getMinimizeBtn();

    /**
     * 获取第一个按钮
     */
    public abstract JFXButton getFirstBtn();

    /**
     * 初始化数据
     */
    public abstract void initData();

    /**
     * 视图样式
     */
    public abstract void initViewStyle();

    /**
     * 视图事件
     */
    public abstract void initViewAction();

    /**
     * 关闭窗口
     */
    public void onDestroy() {
        // 取消所有请求
        EasyHttp.cancel();
        // 停止所有代理隧道
        FrpManager.frpcList.forEach(FrpManager::stop);
        // 保存应用数据
        ApplicatonStore.save();

        Stage stage = (Stage) getRootPanel().getScene().getWindow();
        stage.hide();
        stage.close();
        try {
            Thread.sleep(1000);
            Platform.exit();
            System.exit(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
