package com.szmirren.vxApi.core.verticle;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.time.Instant;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.szmirren.vxApi.core.auth.VxApiClientStaticAuth;
import com.szmirren.vxApi.core.auth.VxApiRolesConstant;
import com.szmirren.vxApi.core.common.PathUtil;
import com.szmirren.vxApi.core.common.ResultFormat;
import com.szmirren.vxApi.core.common.StrUtil;
import com.szmirren.vxApi.core.common.VxApiDATAStoreConstant;
import com.szmirren.vxApi.core.common.VxApiEventBusAddressConstant;
import com.szmirren.vxApi.core.common.VxApiGatewayAttribute;
import com.szmirren.vxApi.core.enums.ContentTypeEnum;
import com.szmirren.vxApi.core.enums.HTTPStatusCodeMsgEnum;
import com.szmirren.vxApi.core.handler.FreeMarkerTemplateHander;
import com.szmirren.vxApi.core.options.VxApiApplicationDTO;
import com.szmirren.vxApi.core.options.VxApisDTO;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.Message;
import io.vertx.core.eventbus.ReplyException;
import io.vertx.core.file.impl.FileResolver;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.common.template.TemplateEngine;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.FaviconHandler;
import io.vertx.ext.web.handler.SessionHandler;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.handler.TemplateHandler;
import io.vertx.ext.web.sstore.ClusteredSessionStore;
import io.vertx.ext.web.sstore.LocalSessionStore;

/**
 * VX-API页面客户端Verticle
 * 
 * @author <a href="http://szmirren.com">Mirren</a>
 *
 */
public class ClientVerticle extends AbstractVerticle {
	private static final Logger LOG = LogManager.getLogger(ClientVerticle.class);

	/**
	 * 返回的CONTENT_TYPE值JSON
	 */
	private final String CONTENT_TYPE = "Content-Type";
	/**
	 * 返回的CONTENT_TYPE值JSON
	 */
	private final String CONTENT_VALUE_JSON_UTF8 = ContentTypeEnum.JSON_UTF8.val();
	/**
	 * 返回的CONTENT_TYPE值HTML
	 */
	private final String CONTENT_VALUE_HTML_UTF8 = ContentTypeEnum.HTML_UTF8.val();
	/**
	 * 没有权限返回
	 */
	private final String UNAUTHORIZED_RESULT = "<h2 style='text-align: center;line-height: 80px;'>对不起!你没有该操作行为的权限  <a href='javascript:history.go(-1);'>返回</a></h2>";
	/**
	 * 没有权限返回
	 */
	private final String _404 = "<h2 style='text-align: center;line-height: 80px;'>Resource not found  <a href='javascript:history.go(-1);'>返回</a></h2>";
	/**
	 * 当前Vertx的唯一标识
	 */
	private String thisVertxName;

	@Override
	public void start(Promise<Void> fut) throws Exception {
		LOG.info("start Client Verticle ...");
		thisVertxName = System.getProperty("thisVertxName", "VX-API");
		Router router = Router.router(vertx);
		router.route().handler(FaviconHandler.create(getFaviconPath()));
		router.route().handler(BodyHandler.create().setUploadsDirectory(getUploadsDirectory()));
		if (vertx.isClustered()) {
			router.route().handler(
					SessionHandler.create(ClusteredSessionStore.create(vertx)).setSessionCookieName(VxApiGatewayAttribute.SESSION_COOKIE_NAME));
		} else {
			router.route()
					.handler(SessionHandler.create(LocalSessionStore.create(vertx)).setSessionCookieName(VxApiGatewayAttribute.SESSION_COOKIE_NAME));
		}
		// 通过html的方式管理应用网关
		// TemplateEngine create = FreeMarkerTemplateEngine.create(vertx);
		// TemplateHandler tempHandler = TemplateHandler.create(create, getTemplateRoot(), CONTENT_VALUE_HTML_UTF8);
		TemplateHandler tempHandler = new FreeMarkerTemplateHander(vertx, getTemplateRoot(), CONTENT_VALUE_HTML_UTF8);
		router.getWithRegex(".+\\.ftl").handler(tempHandler);
		// 权限相关
		router.route("/static/*").handler(VxApiClientStaticAuth.create());
		router.route("/static/*").handler(this::staticAuth);
		router.route("/loginOut").handler(this::loginOut);
		router.route("/static/CreateAPI.html").handler(this::staticAPI);
		router.route("/static/CreateAPP.html").handler(this::staticAPP);

		router.route("/static/*").handler(StaticHandler.create(getStaticRoot()));
		// 查看系统信息
		router.route("/static/sysInfo").handler(this::sysInfo);
		router.route("/static/sysReplaceIpList").handler(this::sysReplaceIpList);
		// Application相关
		router.route("/static/findAPP").handler(this::findAPP);
		router.route("/static/getAPP/:name").handler(this::getAPP);
		router.route("/static/addAPP").handler(this::addAPP);
		router.route("/static/delAPP/:name").handler(this::delAPP);
		router.route("/static/updtAPP/:name").handler(this::loadUpdtAPP);
		router.route("/static/updtAPP").handler(this::updtAPP);

		router.route("/static/deployAPP/:name").handler(this::deployAPP);
		router.route("/static/unDeployAPP/:name").handler(this::unDeployAPP);
		// API相关
		router.route("/static/findAPI/:name").handler(this::findAPI);
		router.route("/static/getAPI/:name").handler(this::getAPI);
		router.route("/static/addAPI").handler(this::addAPI);
		router.route("/static/updtAPI/:name").handler(this::loadUpdtAPI);
		router.route("/static/updtAPI").handler(this::updtAPI);
		router.route("/static/delAPI/:appName/:apiName").handler(this::delAPI);

		router.route("/static/startAllAPI/:appName").handler(this::startAllAPI);
		router.route("/static/startAPI/:apiName").handler(this::startAPI);
		router.route("/static/stopAPI/:appName/:apiName").handler(this::stopAPI);

		router.route("/static/trackInfo/:appName/:apiName").handler(this::getTrackInfo);
		// 欢迎页
		router.route("/").handler(this::welcome);
		vertx.createHttpServer().requestHandler(router).listen(config().getInteger("clientPort", 5256), res -> {
			if (res.succeeded()) {
				LOG.info("start Clinet Verticle successful");
				fut.complete();
			} else {
				LOG.info("start Clinet Verticle unsuccessful");
				fut.fail(res.cause());
			}
		});
	}

	/**
	 * 权限认证
	 * 
	 * @param rct
	 */
	public void staticAuth(RoutingContext rct) {
		User user = rct.user();
		if (user == null) {
			rct.response().end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
		} else {
			user.isAuthorized(VxApiRolesConstant.READ, res -> {
				if (res.succeeded()) {
					if (res.result()) {
						rct.next();
					} else {
						rct.response().end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
					}
				} else {
					rct.response().end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
				}
			});
		}
	}

	/**
	 * 进入创建Application
	 * 
	 * @param rct
	 */
	public void staticAPP(RoutingContext rct) {
		User user = rct.user();
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					rct.next();
				} else {
					rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8).end(UNAUTHORIZED_RESULT);
				}
			} else {
				rct.response().end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 进入创建API
	 * 
	 * @param rct
	 */
	public void staticAPI(RoutingContext rct) {
		User user = rct.user();
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					rct.next();
				} else {
					rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8).end(UNAUTHORIZED_RESULT);
				}
			} else {
				rct.response().end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 查看系统信息
	 * 
	 * @param rct
	 */
	public void sysInfo(RoutingContext rct) {
		LOG.info(MessageFormat.format("[user : {0}] 执行查看运行状态...", rct.session().<String>get("userName")));
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.SYSTEM_GET_INFO, null, reply -> {
			if (reply.succeeded()) {
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, reply.result().body()));
				LOG.info(MessageFormat.format("[user : {0}] 执行查看运行状态...", rct.session().<String>get("userName")));
			} else {
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause().toString()));
				LOG.error(MessageFormat.format("[user : {0}] 查看运行状态-->失败:", rct.session().<String>get("userName"), reply.cause().toString()));
			}
		});
	}

	/**
	 * 更新黑名单地址
	 * 
	 * @param rct
	 */
	public void sysReplaceIpList(RoutingContext rct) {
		LOG.info(MessageFormat.format("[user : {0}] 执行添加IP黑名单...", rct.session().<String>get("userName")));
		JsonArray array = new JsonArray();
		if (rct.getBody() != null || !"".equals(rct.getBodyAsString())) {
			array = new JsonArray(rct.getBodyAsString());
		}
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		JsonObject param = new JsonObject().put("ipList", array);
		vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.SYSTEM_BLACK_IP_REPLACE, param, reply -> {
			if (reply.succeeded()) {
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, reply.result().body()));
				LOG.info(MessageFormat.format("[user : {0}] 执行添加IP黑名单-->结果:", rct.session().<String>get("userName"), reply.result().body()));
			} else {
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause().toString()));
				LOG.error(MessageFormat.format("[user : {0}] 执行添加IP黑名单-->失败:", rct.session().<String>get("userName"), reply.cause().toString()));
			}
		});
	}

	/**
	 * 查看所有应用程序
	 * 
	 * @param rct
	 */
	public void findAPP(RoutingContext rct) {
		LOG.info(MessageFormat.format("[user : {0}] 执行查询应用...", rct.session().<String>get("userName")));
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		// 查询应用是否已经启动
		Future<JsonArray> onlineFuture = Future.future();
		// 查询所有APP
		Future<Message<JsonArray>> findAppFuture = Future.future();
		findAppFuture.setHandler(res -> {
			if (res.succeeded()) {
				JsonArray body = res.result().body();
				if (body.size() > 0) {
					onlineFuture.complete(body);
				} else {
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, body));
				}
			} else {
				LOG.error(MessageFormat.format("[user : {0}] 执行查询应用-->失败:{1}", res.cause().getMessage(), rct.session().<String>get("userName")));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
		onlineFuture.setHandler(res -> {
			// 拓展原来没有显示是否正在运行的属性,如果后期需要优化,可以加多一层业务层,查看应用是否正在运行在业务层处理
			vertx.eventBus().<JsonArray>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_FIND_ONLINE_APP, null, dep -> {
				if (dep.succeeded()) {
					JsonArray body = res.result();
					JsonArray array = new JsonArray();
					JsonArray online = dep.result().body();
					body.forEach(obj -> {
						JsonObject data = (JsonObject) obj;
						JsonObject newObj = new JsonObject();
						String appName = data.getString("appName");
						newObj.put("appName", appName);
						newObj.put("describe", data.getString("describe"));
						newObj.put("time", data.getInstant("time"));
						newObj.put("scope", data.getInteger("scope"));
						newObj.put("online", online.contains(appName));
						array.add(newObj);
					});
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, array));
				} else {
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
				}
			});

		});
		vertx.eventBus().<JsonArray>send(thisVertxName + VxApiEventBusAddressConstant.FIND_APP, null, findAppFuture);
	}

	/**
	 * 查看一个应用程序
	 * 
	 * @param rct
	 */
	public void getAPP(RoutingContext rct) {
		String name = rct.request().getParam("name");
		if (StrUtil.isNullOrEmpty(name)) {
			rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8).end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8);
			// 查看应用使用已经启动
			Future<JsonObject> onlineFutrue = Future.future();
			onlineFutrue.setHandler(res -> {
				vertx.eventBus().<Boolean>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_APP_IS_ONLINE, name, dep -> {
					if (dep.succeeded()) {
						JsonObject body = new JsonObject(res.result().getString("content"));
						body.put("online", dep.result().body());
						JsonObject context = new JsonObject();
						context.put("app", body);
						rct.put("context", context);
						rct.reroute("/getAPP.ftl");
					} else {
						response.end(dep.cause().toString());
					}
				});
			});

			LOG.info(MessageFormat.format("[user : {0}] 执行查看应用-->{1}", rct.session().get("userName"), name));
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_APP, name, res -> {
				if (res.succeeded()) {
					JsonObject body = res.result().body();
					if (body == null || body.isEmpty()) {
						response.setStatusCode(404).end(_404);
						return;
					}
					onlineFutrue.complete(body);
				} else {
					response.end(res.cause().toString());
				}
			});
		}
	}

	/**
	 * 添加应用
	 * 
	 * @param rct
	 */
	public void addAPP(RoutingContext rct) {
		User user = rct.user();
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					LOG.info(MessageFormat.format("[user : {0}] 执行添加应用...", rct.session().<String>get("userName")));
					VxApiApplicationDTO dto = VxApiApplicationDTO.fromJson(rct.getBodyAsJson());
					JsonObject param = new JsonObject();
					param.put("appName", dto.getAppName());
					param.put("app", dto.toJson().put("time", Instant.now()));
					vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.ADD_APP, param, cres -> {
						if (cres.succeeded()) {
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
							LOG.info(MessageFormat.format("[user : {0}] 执行添加应用-->结果: {1}", rct.session().<String>get("userName"), cres.result().body()));
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行添加应用-->失败:{1}", rct.session().get("userName"), cres.cause()));

							if (cres.cause().toString().contains("UNIQUE")) {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C1444, cres.cause().toString()));
							} else {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
							}
						}
					});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行添加应用-->失败:未授权或者无权利", rct.session().get("userName")));
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
				}
			} else {
				LOG.error(MessageFormat.format("[user : {0}] 执行添加应用-->失败:{1}", rct.session().get("userName"), res.cause()));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 渲染一个将要修改的应用程序
	 * 
	 * @param rct
	 */
	public void loadUpdtAPP(RoutingContext rct) {
		String name = rct.request().getParam("name");
		if (StrUtil.isNullOrEmpty(name)) {
			rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8).end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8);
			LOG.info(MessageFormat.format("[user : {0}] 执行查看应用-->{1}", rct.session().get("userName"), name));
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_APP, name, res -> {
				if (res.succeeded()) {
					JsonObject body = res.result().body();
					JsonObject app = new JsonObject(body.getString("content"));
					if (app.isEmpty()) {
						response.setStatusCode(404).end(_404);
					} else {
						JsonObject context = new JsonObject();
						context.put("app", app);
						rct.put("context", context);
						rct.reroute("/updateAPP.ftl");
					}
				} else {
					response.end(res.cause().toString());
				}
			});
		}
	}

	/**
	 * 修改一个应用
	 * 
	 * @param rct
	 */
	public void updtAPP(RoutingContext rct) {
		User user = rct.user();
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					LOG.info(MessageFormat.format("[user : {0}] 执行修改应用...", rct.session().<String>get("userName")));
					VxApiApplicationDTO dto = VxApiApplicationDTO.fromJson(rct.getBodyAsJson());
					JsonObject param = new JsonObject();
					param.put("appName", dto.getAppName());
					param.put("app", dto.toJson());
					vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.UPDT_APP, param, cres -> {
						if (cres.succeeded()) {
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
							LOG.info(MessageFormat.format("[user : {0}] 执行修改应用:{2}-->结果: {1}", rct.session().<String>get("userName"),
									cres.result().body(), dto.getAppName()));
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行修改应用-->失败:{1}", rct.session().get("userName"), cres.cause()));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
						}
					});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行修改应用-->失败:未授权或者无权利", rct.session().get("userName")));
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
				}
			} else {
				LOG.error(MessageFormat.format("[user : {0}] 执行修改应用-->失败:{1}", rct.session().get("userName"), res.cause()));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 删除应用程序
	 * 
	 * @param rct
	 */
	public void delAPP(RoutingContext rct) {
		String name = rct.request().getParam("name");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(name)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			User user = rct.user();
			user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
				if (res.succeeded()) {
					JsonObject config = new JsonObject().put("appName", name);
					vertx.eventBus().send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_APP_UNDEPLOY, config);
					if (res.result()) {
						// 将应用暂停
						if (vertx.isClustered()) {
							vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_APP_UNDEPLOY, config.copy().put("thisVertxName", thisVertxName));
							LOG.info("执行删除应用-->广播告诉集群环境中暂停应用:" + name);
						}
						LOG.info(MessageFormat.format("[user : {0}] 执行删除应用{1}...", rct.session().<String>get("userName"), name));
						vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.DEL_APP, name, cres -> {
							if (cres.succeeded()) {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
								LOG.info(MessageFormat.format("[user : {0}] 执行删除应用:{2}-->结果: {1}", rct.session().<String>get("userName"),
										cres.result().body(), name));
							} else {
								LOG.error(MessageFormat.format("[user : {0}] 执行删除应用:{2}-->失败:{1}", rct.session().get("userName"), cres.cause(), name));
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
							}
						});
					} else {
						LOG.error(MessageFormat.format("[user : {0}] 执行删除应用:{1}-->失败:未授权或者无权限", rct.session().get("userName"), name));
						response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
					}
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行删除应用:{2}-->失败:{1}", rct.session().get("userName"), res.cause(), name));
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
				}
			});
		}
	}

	/**
	 * 启动应用
	 * 
	 * @param rct
	 */
	public void deployAPP(RoutingContext rct) {
		String name = rct.request().getParam("name");
		LOG.info("执行启动应用-->" + name + "...");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(name)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_APP, name, body -> {
				if (body.succeeded()) {
					if (body.result().body().isEmpty()) {
						response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
					} else {
						JsonObject app = new JsonObject(body.result().body().getString("content"));
						JsonObject config = new JsonObject();
						config.put("app", app);
						config.put("appName", name);
						vertx.eventBus().<String>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_APP_DEPLOY, config, deploy -> {
							if (deploy.succeeded()) {
								LOG.info("启动应用-->" + name + ":成功!");
								response.end(ResultFormat.formatAsOne(HTTPStatusCodeMsgEnum.C200));
								if (vertx.isClustered()) {
									vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_APP_DEPLOY,
											config.copy().put("thisVertxName", thisVertxName));
									LOG.info("广播告诉集群环境中启动应用:" + name);
								}
							} else {
								LOG.error("启动应用-->" + name + " 失败:" + deploy.cause());
								HTTPStatusCodeMsgEnum msgCode = HTTPStatusCodeMsgEnum.C500;
								if (deploy.cause() != null && deploy.cause() instanceof ReplyException) {
									ReplyException cause = (ReplyException) deploy.cause();
									if (cause.failureCode() == 1111) {
										msgCode = HTTPStatusCodeMsgEnum.C1111;
									}
								}
								response.end(ResultFormat.formatAsZero(msgCode));
							}
						});
					}
				} else {
					LOG.error("启动应用-->" + name + " 失败:" + body.cause());
					System.out.println("启动应用-->" + name + " 失败:" + body.cause());
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C500));
				}
			});
		}
	}

	/**
	 * 卸载应用
	 * 
	 * @param rct
	 */
	public void unDeployAPP(RoutingContext rct) {
		String name = rct.request().getParam("name");
		LOG.info("执行暂停应用-->" + name + "...");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(name)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			JsonObject config = new JsonObject().put("appName", name);
			vertx.eventBus().<String>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_APP_UNDEPLOY, config, deploy -> {
				if (deploy.succeeded()) {
					LOG.info("执行暂停应用-->" + name + " 成功!");
					response.end(ResultFormat.formatAsOne(HTTPStatusCodeMsgEnum.C200));
					if (vertx.isClustered()) {
						vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_APP_UNDEPLOY, config.copy().put("thisVertxName", thisVertxName));
						LOG.info("广播集群环境中启动应用:" + name);
					}
				} else {
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C500));
					LOG.error("执行暂停应用-->" + name + " 失败:" + deploy.cause());
				}
			});
		}
	}

	// =============================================
	// ====================APIS=====================
	// =============================================

	/**
	 * 查看所有API
	 * 
	 * @param rct
	 */
	public void findAPI(RoutingContext rct) {
		String name = rct.request().getParam("name");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(name)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			MessageFormat.format("[user : {0}] 执行查询所以API...", rct.session().<String>get("userName"));
			JsonObject body = new JsonObject();
			body.put("appName", name);
			String limit = rct.request().getParam("limit");
			String offset = rct.request().getParam("offset");
			if (limit != null && !"".equals(limit.trim())) {
				body.put("limit", new Integer(limit));
			} else {
				body.put("limit", 20);
			}
			if (offset != null && !"".equals(offset.trim())) {
				body.put("offset", new Integer(offset));
			} else {
				body.put("offset", 0);
			}
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.FIND_API_BY_PAGE, body, res -> {
				if (res.succeeded()) {
					vertx.eventBus().<JsonArray>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_FIND_ONLINE_API,
							new JsonObject().put("appName", name), reply -> {
								if (reply.succeeded()) {
									JsonArray online = reply.result().body();
									JsonObject result = res.result().body();
									result.getJsonArray("data").forEach(data -> {
										String apiName = ((JsonObject) data).getString("apiName");
										((JsonObject) data).put("online", online.contains(apiName));
									});
									response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, result));
								} else {
									LOG.error(MessageFormat.format("[user : {0}] 执行查询在线API-->失败:{1}", res.cause().getMessage(),
											rct.session().<String>get("userName")));
									response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
								}
							});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行查询API-->失败:{1}", res.cause().getMessage(), rct.session().<String>get("userName")));
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
				}
			});
		}
	}

	/**
	 * 查看一个API
	 * 
	 * @param rct
	 */
	public void getAPI(RoutingContext rct) {
		String name = rct.request().getParam("name");
		if (StrUtil.isNullOrEmpty(name)) {
			rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8).end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8);

			LOG.info(MessageFormat.format("[user : {0}] 执行查看API-->{1}", rct.session().get("userName"), name));
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_API, name, res -> {
				if (res.succeeded()) {
					if (res.result().body() == null || res.result().body().isEmpty()) {
						response.setStatusCode(404).end(_404);
						return;
					}
					JsonObject body = res.result().body();
					String appName = body.getString(VxApiDATAStoreConstant.API_APP_ID_NAME);
					JsonObject isOnLineConf = new JsonObject();
					isOnLineConf.put("appName", appName);
					isOnLineConf.put("apiName", name);
					vertx.eventBus().<Boolean>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_API_IS_ONLINE, isOnLineConf, dep -> {
						if (dep.succeeded()) {
							JsonObject api = new JsonObject(body.getString(VxApiDATAStoreConstant.API_CONTENT_NAME));
							api.put("online", dep.result().body());
							if (api.getValue("serverEntrance") instanceof JsonObject) {
								if ("CUSTOM".equals(api.getJsonObject("serverEntrance").getValue("serverType"))) {
									if (api.getJsonObject("serverEntrance").getValue("body") instanceof JsonObject) {
										JsonObject custom = api.getJsonObject("serverEntrance").getJsonObject("body");
										api.put("customFactoryName", custom.getString("inFactoryName"));
										custom.remove("inFactoryName");
										api.put("customBody", custom.toString());
									}
								}
							}
							JsonObject context = new JsonObject();
							context.put("api", api);
							rct.put("context", context);
							rct.reroute("/getAPI.ftl");
						} else {
							LOG.error(
									MessageFormat.format("[user : {0}] 执行查看API:{1}-->失败:{2}", rct.session().get("userName"), name, dep.cause().toString()));
							response.end(dep.cause().toString());
						}
					});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行查看API:{1}-->失败:{2}", rct.session().get("userName"), name, res.cause().toString()));
					response.end(res.cause().toString());
				}
			});
		}
	}

	/**
	 * 添加一个API
	 * 
	 * @param rct
	 */
	public void addAPI(RoutingContext rct) {
		User user = rct.user();
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					LOG.info(MessageFormat.format("[user : {0}] 执行添加API...", rct.session().<String>get("userName")));
					JsonObject bodyAsJson = rct.getBodyAsJson();
					VxApisDTO dto = VxApisDTO.fromJson(bodyAsJson);
					dto.setApiCreateTime(Instant.now());
					JsonObject param = new JsonObject();
					param.put("apiName", dto.getApiName());
					param.put("appName", dto.getAppName());
					param.put("api", dto.toJson());
					vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.ADD_API, param, cres -> {
						if (cres.succeeded()) {
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
							LOG.info(MessageFormat.format("[user : {0}] 执行添加API-->结果: {1}", rct.session().<String>get("userName"), cres.result().body()));
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行添加API-->失败:{1}", rct.session().get("userName"), cres.cause()));
							if (cres.cause().toString().contains("UNIQUE")) {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C1444, cres.cause().toString()));
							} else {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
							}
						}
					});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行添加API-->失败:未授权或者无权利", rct.session().get("userName")));
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
				}
			} else {
				LOG.error(MessageFormat.format("[user : {0}] 执行添加API-->失败:{1}", rct.session().get("userName"), res.cause()));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 加载更新API需要的数据
	 * 
	 * @param rct
	 */
	public void loadUpdtAPI(RoutingContext rct) {
		String name = rct.request().getParam("name");
		if (StrUtil.isNullOrEmpty(name)) {
			rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8).end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1404));
		} else {
			LOG.info(MessageFormat.format("[user : {0}] 执行查看API-->{1}", rct.session().get("userName"), name));
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_API, name, res -> {
				if (res.succeeded()) {
					JsonObject body = res.result().body();
					JsonObject api = new JsonObject(body.getString(VxApiDATAStoreConstant.API_CONTENT_NAME));
					if (api.isEmpty()) {
						rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8).setStatusCode(404).end(_404);
					} else {
						// 添加认证配置文件为字符串
						if (api.getValue("authOptions") != null) {
							api.put("authOptionBody", api.getJsonObject("authOptions").getJsonObject("option").toString());
						}
						// 添加前置处理器配置文件为字符串
						if (api.getValue("beforeHandlerOptions") != null) {
							api.put("beforeHandlerOptionsBody", api.getJsonObject("beforeHandlerOptions").getJsonObject("option").toString());
						}
						// 添加后置处理器配置文件为字符串
						if (api.getValue("afterHandlerOptions") != null) {
							api.put("afterHandlerOptionsBody", api.getJsonObject("afterHandlerOptions").getJsonObject("option").toString());
						}
						if (api.getValue("serverEntrance") instanceof JsonObject) {
							if ("CUSTOM".equals(api.getJsonObject("serverEntrance").getValue("serverType"))) {
								if (api.getJsonObject("serverEntrance").getValue("body") instanceof JsonObject) {
									JsonObject custom = api.getJsonObject("serverEntrance").getJsonObject("body");
									api.put("customFactoryName", custom.getString("inFactoryName"));
									custom.remove("inFactoryName");
									custom.remove("params");
									api.put("customBody", custom.toString());
								}
							}
						}
						JsonObject context = new JsonObject();
						context.put("api", api);
						rct.put("context", context);
						rct.reroute("/updateAPI.ftl");
					}
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行查看API:{1}-->失败:{2}", rct.session().get("userName"), name, res.cause().toString()));
					rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8).end(res.cause().toString());
				}
			});
		}
	}

	/**
	 * 更新一个API
	 * 
	 * @param rct
	 */
	public void updtAPI(RoutingContext rct) {
		User user = rct.user();
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		user.isAuthorized(VxApiRolesConstant.WRITE, res -> {
			if (res.succeeded()) {
				if (res.result()) {
					LOG.info(MessageFormat.format("[user : {0}] 执行修改应用...", rct.session().<String>get("userName")));
					VxApisDTO dto = VxApisDTO.fromJson(rct.getBodyAsJson());
					if (dto.getApiCreateTime() == null) {
						dto.setApiCreateTime(Instant.now());
					}
					JsonObject param = new JsonObject();
					param.put("apiName", dto.getApiName());
					param.put("api", dto.toJson());
					vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.UPDT_API, param, cres -> {
						if (cres.succeeded()) {
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
							LOG.info(MessageFormat.format("[user : {0}] 执行修改API:{2}-->结果: {1}", rct.session().<String>get("userName"),
									cres.result().body(), dto.getApiName()));
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行修改API-->失败:{1}", rct.session().get("userName"), cres.cause()));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
						}
					});
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行修改API-->失败:未授权或者无权利", rct.session().get("userName")));
					response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
				}
			} else {
				LOG.error(MessageFormat.format("[user : {0}] 执行修改API-->失败:{1}", rct.session().get("userName"), res.cause()));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
			}
		});
	}

	/**
	 * 删除一个API
	 * 
	 * @param rct
	 */
	public void delAPI(RoutingContext rct) {
		String apiName = rct.request().getParam("apiName");
		String appName = rct.request().getParam("appName");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(appName, apiName)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1400));
		} else {

			User user = rct.user();
			user.isAuthorized(VxApiRolesConstant.WRITE, res -> {

				if (res.succeeded()) {
					JsonObject body = new JsonObject();
					body.put("apiName", apiName);
					body.put("appName", appName);
					if (res.result()) {
						LOG.info(MessageFormat.format("[user : {0}] 执行删除API:{1}...", rct.session().<String>get("userName"), apiName));
						vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.DEL_API, body, cres -> {
							if (cres.succeeded()) {
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, cres.result().body()));
								LOG.info(MessageFormat.format("[user : {0}] 执行删除API:{2}-->结果: {1}", rct.session().<String>get("userName"),
										cres.result().body(), apiName));
								if (vertx.isClustered()) {
									vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_API_STOP, body.copy().put("thisVertxName", thisVertxName));
									LOG.info("广播告诉集群环境中暂停应用:" + appName + "的" + apiName + "API");
								}
							} else {
								LOG.error(MessageFormat.format("[user : {0}] 执行删除API:{2}-->失败:{1}", rct.session().get("userName"), cres.cause(), apiName));
								response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, cres.cause().toString()));
							}
						});
					} else {
						LOG.error(MessageFormat.format("[user : {0}] 执行删除API:{1}-->失败:未授权或者无权限", rct.session().get("userName"), apiName));
						response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C401));
					}
				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行删除API:{2}-->失败:{1}", rct.session().get("userName"), res.cause(), apiName));
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().getMessage()));
				}
			});
		}

	}

	/**
	 * 启动所有API
	 * 
	 * @param rct
	 */
	public void startAllAPI(RoutingContext rct) {
		String appName = rct.request().getParam("appName");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(appName)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1400));
		} else {
			LOG.info(MessageFormat.format("[user : {0}] 执行启动应用{1}:所有API..", rct.session().get("userName"), appName));
			// 用于获取所有API的参数
			JsonObject message = new JsonObject().put("appName", appName);
			// 获取所有API
			vertx.eventBus().<JsonArray>send(thisVertxName + VxApiEventBusAddressConstant.FIND_API_ALL, message, data -> {
				if (data.succeeded()) {
					JsonArray body = data.result().body();
					DeliveryOptions option = new DeliveryOptions();
					option.setSendTimeout(200 * 301);
					JsonObject config = new JsonObject();
					config.put("appName", appName);
					config.put("apis", body);
					vertx.eventBus().<String>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_API_START_ALL, config, option, reply -> {
						if (reply.succeeded()) {
							LOG.info(MessageFormat.format("[user : {0}] 执行启动应用{1}:所有API-->成功", rct.session().get("userName"), appName));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, reply.result().body()));
							if (vertx.isClustered()) {
								vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_API_START_ALL,
										config.copy().put("thisVertxName", thisVertxName));
								LOG.info("广播通知集群环境中 应用:" + appName + ",启动所有API");
							}
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行启动所有API-->查看API:{1}-->失败:{2}", rct.session().get("userName"), appName,
									reply.cause().toString()));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause().toString()));
						}
					});

				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行启动所有API-->查看API:{1}-->失败:{2}", rct.session().get("userName"), appName,
							data.cause().toString()));
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, data.cause().toString()));
				}
			});
		}
	}

	/**
	 * 启动一个API
	 * 
	 * @param rct
	 */
	public void startAPI(RoutingContext rct) {
		String apiName = rct.request().getParam("apiName");
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		if (StrUtil.isNullOrEmpty(apiName)) {
			response.end(ResultFormat.formatAsZero(HTTPStatusCodeMsgEnum.C1400));
		} else {

			LOG.info(MessageFormat.format("[user : {0}] 执行启动API-->{1}", rct.session().get("userName"), apiName));
			vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.GET_API, apiName, res -> {
				if (res.succeeded()) {
					JsonObject body = res.result().body();
					String appName = body.getString(VxApiDATAStoreConstant.API_APP_ID_NAME);
					JsonObject api = new JsonObject(body.getString(VxApiDATAStoreConstant.API_CONTENT_NAME));
					JsonObject data = new JsonObject();
					data.put("appName", appName);
					data.put("apiName", apiName);
					data.put("api", api);
					vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_API_START, data, reply -> {
						if (reply.succeeded()) {
							Integer result = reply.result().body();
							LOG.info(MessageFormat.format("[user : {0}] 执行启动API-->{1},结果:{2}", rct.session().get("userName"), apiName, result));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, result));
							if (vertx.isClustered()) {
								vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_API_START, data.copy().put("thisVertxName", thisVertxName));
								LOG.info("广播告诉集群环境中启动应用:" + appName + "的" + apiName + "API");
							}
						} else {
							LOG.error(MessageFormat.format("[user : {0}] 执行启动API:{1}-->失败:{2}", rct.session().get("userName"), apiName,
									reply.cause().toString()));
							response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause().toString()));
						}
					});

				} else {
					LOG.error(MessageFormat.format("[user : {0}] 执行启动API-->查看API:{1}-->失败:{2}", rct.session().get("userName"), apiName,
							res.cause().toString()));
					response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, res.cause().toString()));
				}
			});
		}

	}

	/**
	 * 启动一个API
	 * 
	 * @param rct
	 */
	public void stopAPI(RoutingContext rct) {
		String appName = rct.request().getParam("appName");
		String apiName = rct.request().getParam("apiName");
		JsonObject body = new JsonObject();
		body.put("appName", appName);
		body.put("apiName", apiName);
		HttpServerResponse response = rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8);
		LOG.info(MessageFormat.format("[user : {0}] 执行暂停API-->{1}", rct.session().get("userName"), apiName));
		vertx.eventBus().<Integer>send(thisVertxName + VxApiEventBusAddressConstant.DEPLOY_API_STOP, body, reply -> {
			if (reply.succeeded()) {
				Integer result = reply.result().body();
				LOG.info(MessageFormat.format("[user : {0}] 执行暂停API:{1}-->结果:{2}", rct.session().get("userName"), apiName, result));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, result));
				if (vertx.isClustered()) {
					vertx.eventBus().publish(VxApiEventBusAddressConstant.DEPLOY_API_STOP, body.copy().put("thisVertxName", thisVertxName));
					LOG.info("广播告诉集群环境中暂停应用:" + appName + "的" + apiName + "API");
				}
			} else {
				LOG.error(
						MessageFormat.format("[user : {0}] 执行暂停API:{1}-->失败:{2}", rct.session().get("userName"), apiName, reply.cause().toString()));
				response.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause().toString()));
			}
		});

	}

	/**
	 * 查看API监控信息
	 * 
	 * @param rct
	 */
	public void getTrackInfo(RoutingContext rct) {
		String appName = rct.request().getParam("appName");
		String apiName = rct.request().getParam("apiName");
		JsonObject msg = new JsonObject();
		msg.put("appName", appName);
		msg.put("apiName", apiName);
		vertx.eventBus().<JsonObject>send(thisVertxName + VxApiEventBusAddressConstant.SYSTEM_GET_TRACK_INFO, msg, reply -> {
			if (reply.succeeded()) {
				rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8)
						.end(ResultFormat.format(HTTPStatusCodeMsgEnum.C200, reply.result().body()));
			} else {
				rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_JSON_UTF8).end(ResultFormat.format(HTTPStatusCodeMsgEnum.C500, reply.cause()));
			}
		});
	}

	/**
	 * 退出登录
	 * 
	 * @param rct
	 */
	public void loginOut(RoutingContext rct) {
		if (rct.user() != null) {
			rct.user().clearCache();
		}
		rct.session().remove(VxApiClientStaticAuth.AUTHORIZATION);
		rct.session().put(VxApiClientStaticAuth.IS_AUTH, "false");
		rct.response().putHeader("Location", "/").setStatusCode(302).end();
	}

	/**
	 * 欢迎
	 * 
	 * @param rct
	 */
	public void welcome(RoutingContext rct) {
		rct.response().putHeader(CONTENT_TYPE, CONTENT_VALUE_HTML_UTF8).end("<h1 style='text-align: center;margin-top: 5%;'>Hello VX-API "
				+ VxApiGatewayAttribute.VERSION
				+ " <br><a href=\"http://duhua.gitee.io/vx-api-gateway-doc/\"> 查看帮助文档</a> <br> <a href=\"static/Application.html\">进入首页</a></h1>");
	}

	/**
	 * 获得客户端的 Favicon图标
	 * 
	 * @return
	 */
	public String getFaviconPath() {
		if (PathUtil.isJarEnv()) {
			return "../conf/static/logo.png";
		} else {
			return "static/logo.png";
		}
	}

	/**
	 * 获得静态文件的根目录
	 * 
	 * @return
	 */
	public String getStaticRoot() {
		if (PathUtil.isJarEnv()) {
			return "../conf/static";
		} else {
			return "static";
		}
	}

	/**
	 * 获得模板的路径
	 * 
	 * @return
	 */
	public String getTemplateRoot() {
		if (PathUtil.isJarEnv()) {
			FileResolver fileResolver = new FileResolver();
			File file = fileResolver.resolveFile(new File(PathUtil.getPathString("templates")).getPath());
			return (file.getPath().startsWith("/") ? "" : "/") + file.getPath();
		} else {
			return "target/classes/templates";
		}

	}

	/**
	 * 获得文件上传的文件夹路径
	 * 
	 * @return
	 */
	public String getUploadsDirectory() {
		if (PathUtil.isJarEnv()) {
			return "../temp/file-uploads";
		} else {
			return "file-uploads";
		}
	}

}