package com.sf.apijson.config;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sf.common.constant.GenConstants;
import com.sf.generator.domain.GenTable;
import com.sf.generator.domain.GenTableColumn;
import com.sf.generator.util.VelocityUtils;

import apijson.JSONResponse;
import apijson.RequestMethod;

/***
 * 为某一张表生成 <br/>
 * 1、新增、修改、删除、查询 Access、Request、Document配置 <br/>
 * 2、增量初始化APIJSON 配置(后置函数) <br/>
 * 3、前置/后置函数 对数据进行二次处理 <br/>
 * 4、参数校验规则 必传参数、数据类型判断、参数正则校验等 <br/>
 * 5、应用前端模版,生成页面 <br/>
 * 6、配置菜单等表数据,将页面挂载到某一个菜单上面 <br/>
 * 7、配置url 权限, 比如 sa-token, Spring Security 等<br/>
 * 8、假删除 <br/>
 * 9、将表信息存储到缓存中, 插入数据判断 表主键字段字和增长方式
 * 
 *
 */
public class BuildApijsonAccessConfig {
	private static final Logger log = LoggerFactory.getLogger(BuildApijsonAccessConfig.class);

	public static void main(String[] args) {
		JSONArray ids = new JSONArray();
		ids.add("1");
		ids.add("2");

		JSONObject delObj = new JSONObject(true);
		delObj.put("format", true);
		delObj.put("@explain", true);
		delObj.put("tag", "Access");
		JSONObject delObjItem = new JSONObject(true);
		delObjItem.put("id{}", ids.toArray());
		delObj.put("Access", delObjItem);
		log.info("查询json:{}", delObj.toJSONString());
	}

	public static void deleteRequestConfig(JSONArray tag, HttpSession session) {
		JSONObject obj = new JSONObject(true);
		obj.put("tag", "Request");
		JSONObject objItem = new JSONObject(true);
		JSONObject tableItem = new JSONObject(true);
		tableItem.put("@column", "id");
		tableItem.put("tag{}", tag);
		objItem.put("page", 0);
		objItem.put("count", 100);
		objItem.put("query", 2);
		objItem.put("Request", tableItem);
		obj.put("Request:data[]", objItem);
		obj.put("total@", "/Request:data[]/total");
		obj.put("format", true);
		obj.put("@explain", true);
		log.info("查询json:{}", obj.toJSONString());

		JSONObject response = new FormParser(RequestMethod.GET).setSession(session).setNeedVerify(false)
				.parseResponse(obj);
		JSONResponse responseJson = new JSONResponse(response);
		if (responseJson.isSuccess() && responseJson.getInteger("total") > 0
				&& responseJson.getJSONArray("data").size() > 0) {
			JSONArray ids = new JSONArray();
			for (int i = 0; i < responseJson.getJSONArray("data").size(); i++) {
				JSONObject jsonObject = responseJson.getJSONArray("data").getJSONObject(i);
				ids.add(jsonObject.get("id"));
			}

			JSONObject delObj = new JSONObject(true);
			delObj.put("format", true);
			delObj.put("@explain", true);
			delObj.put("tag", "Request");
			JSONObject delObjItem = new JSONObject(true);
			delObjItem.put("id{}", ids);
			delObj.put("Request", delObjItem);
			response = new FormParser(RequestMethod.DELETE).setSession(session).setNeedVerify(false)
					.parseResponse(delObj);
			log.info("删除Request:{}", response.toJSONString());
		}
	}

	public static void deleteDocumentConfig(String url, HttpSession session) {
		JSONObject obj = new JSONObject(true);
		JSONObject objItem = new JSONObject(true);
		JSONObject tableItem = new JSONObject(true);
		tableItem.put("@column", "id");
		tableItem.put("url~", url);
		objItem.put("page", 0);
		objItem.put("count", 100);
		objItem.put("query", 2);
		objItem.put("Document", tableItem);
		obj.put("Document:data[]", objItem);
		obj.put("total@", "/Document:data[]/total");
		obj.put("tag", "Document");
		obj.put("format", true);
		obj.put("@explain", true);
		log.info("查询json:{}", obj.toJSONString());

		JSONObject response = new FormParser(RequestMethod.GET).setSession(session).setNeedVerify(false)
				.parseResponse(obj);
		JSONResponse responseJson = new JSONResponse(response);
		if (responseJson.isSuccess() && responseJson.getInteger("total") > 0
				&& responseJson.getJSONArray("data").size() > 0) {
			JSONArray ids = new JSONArray();
			for (int i = 0; i < responseJson.getJSONArray("data").size(); i++) {
				JSONObject jsonObject = responseJson.getJSONArray("data").getJSONObject(i);
				ids.add(jsonObject.get("id"));
			}

			JSONObject delObj = new JSONObject(true);
			delObj.put("format", true);
			delObj.put("@explain", true);
			delObj.put("tag", "Document");
			JSONObject delObjItem = new JSONObject(true);
			delObjItem.put("id{}", ids);
			delObj.put("Document", delObjItem);
			response = new FormParser(RequestMethod.DELETE).setSession(session).setNeedVerify(false)
					.parseResponse(delObj);
			log.info("删除Document:{}", response.toJSONString());
		}
	}

	public static void deleteAccessConfig(String tag, HttpSession session) {
		JSONObject obj = new JSONObject(true);
		obj.put("tag", "Access");
		JSONObject objItem = new JSONObject(true);
		JSONObject tableItem = new JSONObject(true);
		tableItem.put("@column", "id");
		tableItem.put("name", tag);
		objItem.put("page", 0);
		objItem.put("count", 100);
		objItem.put("query", 2);
		objItem.put("Access", tableItem);
		obj.put("Access:data[]", objItem);
		obj.put("total@", "/Access:data[]/total");
		obj.put("format", true);
		obj.put("@explain", true);
		log.info("查询json:{}", obj.toJSONString());

		JSONObject response = new FormParser(RequestMethod.GET).setSession(session).setNeedVerify(false)
				.parseResponse(obj);
		JSONResponse responseJson = new JSONResponse(response);
		if (responseJson.isSuccess() && responseJson.getInteger("total") > 0
				&& responseJson.getJSONArray("data").size() > 0) {
			JSONArray ids = new JSONArray();
			for (int i = 0; i < responseJson.getJSONArray("data").size(); i++) {
				JSONObject jsonObject = responseJson.getJSONArray("data").getJSONObject(i);
				ids.add(jsonObject.get("id"));
			}
			JSONObject delObj = new JSONObject(true);
			delObj.put("format", true);
			delObj.put("@explain", true);
			delObj.put("tag", "Access");
			JSONObject delObjItem = new JSONObject(true);
			delObjItem.put("id{}", ids);
			delObj.put("Access", delObjItem);
			response = new FormParser(RequestMethod.DELETE).setSession(session).setNeedVerify(false)
					.parseResponse(delObj);
			log.info("删除Access:{}", response.toJSONString());
		}
	}

	public static JSONObject generatorJsonCode(GenTable table, String urlSuffix, HttpSession session) throws Exception {
		JSONObject autoCreateConfig = autoCreateConfig(table, urlSuffix);
		log.info("autoCreateConfig:{}", autoCreateConfig.toString());

		JSONObject response = new FormParser(RequestMethod.CRUD).setSession(session).setNeedVerify(true)
				.parseResponse(autoCreateConfig);
		log.info("generatorCode response:{}", response);

		// 前置函数已经做了 增量初始化配置
		JSONResponse responseJson = new JSONResponse(response);
		if (responseJson.isSuccess()) {
			ApijsonInitUtil.addInitAccess(response.getJSONObject("access").getLong("id"));
			for (Object requestId : response.getJSONObject("request").getJSONArray("id")) {
				ApijsonInitUtil.addInitRequest(Long.valueOf(requestId.toString()));
			}
			for (Object requestId : response.getJSONObject("document").getJSONArray("id")) {
				ApijsonInitUtil.addInitDocument(Long.valueOf(requestId.toString()));
			}
		}
		return response;
	}

	public static JSONObject generatorCodeRawSQL(String url, String urlSuffix, JSONObject requestJson,
			HttpSession session) throws Exception {
		// crud方法
		JSONObject crud = new JSONObject(true);
		JSONObject crudPost = new JSONObject(true);

		JSONObject crudDocumentPost = new JSONObject(true);
		crudDocumentPost.put("tag", "Document");
		crudPost.put("Document", crudDocumentPost);

		JSONObject crudRequestPost = new JSONObject(true);
		crudRequestPost.put("tag", "Request");
		crudPost.put("Request", crudRequestPost);

		crud.put("@post", crudPost);

		// document
		JSONObject document = new JSONObject(true);
		document.put("debug", 0);
		document.put("testAccountId", 0);
		document.put("version", 3);
		document.put("name", requestJson.getString("name")); // 接口名称
		document.put("type", "JSON");
		document.put("url", url);
		document.put("request", "{}");
		document.put("apijson", requestJson.getString("apijson"));
		// TODO 只能是查询sql,需要检测
		document.put("sqlauto", requestJson.getString("sqlauto"));

		// request
		// 单条新增
		JSONObject requestItem_post = new JSONObject(true);
		requestItem_post.put("method", RequestMethod.GET.name());
		requestItem_post.put("tag", urlSuffix);
		requestItem_post.put("detail", requestJson.getString("name"));
		JSONObject requestItem_structure = new JSONObject(true);

		// 必传字段
		// must: a,b
		if (StringUtils.isNotBlank(requestJson.getString("must"))) {
			requestItem_structure.put("MUST", requestJson.getString("must"));
		}
		// TODO TYPE 数据类型
		if (StringUtils.isNotBlank(requestJson.getString("type"))) {
			requestItem_structure.put("TYPE", requestJson.getJSONObject("type"));
		}
		// TODO VERIFY 参数校验
		if (StringUtils.isNotBlank(requestJson.getString("verify"))) {
			requestItem_structure.put("VERIFY", requestJson.getJSONObject("verify"));
		}
		requestItem_post.put("structure", requestItem_structure.toString());

		crud.put("@post", crudPost);
		crud.put("Request", requestItem_post);
		crud.put("Document", document);
		crud.put("format", true);
		crud.put("@explain", true);
		return crud;
	}

	public static JSONObject generatorCodeJSON(String url, String urlSuffix, JSONObject requestJson,
			HttpSession session) throws Exception {
		JSONObject apijson = requestJson.getJSONObject("apijson");
		// crud方法
		JSONObject crud = new JSONObject(true);
		JSONObject crudPost = new JSONObject(true);

		JSONObject crudDocumentPost = new JSONObject(true);
		crudDocumentPost.put("tag", "Document");
		crudPost.put("Document", crudDocumentPost);

		JSONObject crudRequestPost = new JSONObject(true);
		crudRequestPost.put("tag", "Request");
		crudPost.put("Request", crudRequestPost);

		crud.put("@post", crudPost);

		// document
		JSONObject document = new JSONObject(true);
		document.put("debug", 0);
		document.put("testAccountId", 0);
		document.put("version", 3);
		document.put("name", requestJson.getString("name")); // 接口名称
		document.put("type", "JSON");
		document.put("url", url);
		document.put("request", "{}");
		if(StringUtils.isNotBlank(requestJson.getString("sqlauto"))) {
			apijson.put("request_tag", urlSuffix);
			document.put("sqlauto", requestJson.getString("sqlauto"));
		}
		document.put("apijson", apijson.toJSONString());
		// request
		JSONObject requestItem_post = new JSONObject(true);
		requestItem_post.put("method", requestJson.getString("method").toUpperCase());
		requestItem_post.put("tag", urlSuffix);
		requestItem_post.put("detail", requestJson.getString("name"));
		requestItem_post.put("structure", requestJson.getString("structure"));

		crud.put("@post", crudPost);
		crud.put("Request", requestItem_post);
		crud.put("Document", document);
		crud.put("format", true);
		crud.put("@explain", true);
		return crud;
	}

	public static JSONObject autoCreateConfig(GenTable table, String urlSuffix) throws IllegalAccessException {
		// crud方法一起执行
		JSONObject accessPost = buildAccess(table);
		JSONObject buildRequestPost = buildRequestPost(table, null);
		JSONObject buildRequestBatchPost = buildRequestBatchPost(table, null);
		JSONObject buildRequestPutById = buildRequestPutById(table, null);
		JSONObject buildRequestBatchPutByIds = buildRequestBatchPutByIds(table, null);
		JSONObject buildRequestDeleteByIds = buildRequestDeleteByIds(table, null);

		// router 不能沿用 json request 配置, 比如 unique 会有问题, 无法找到数据库表
		JSONObject buildDocumentRequestPost = buildRequestPost(table, urlSuffix);
		JSONObject buildDocumentRequestPutById = buildRequestPutById(table, urlSuffix);
		JSONObject buildDocumentRequestDeleteByIds = buildRequestDeleteByIds(table, urlSuffix);
		JSONObject buildDocumentRequestList = buildRequestList(table, urlSuffix + "list");
		JSONObject buildDocumentRequestDetail = buildRequestDetail(table, urlSuffix);
		
		JSONObject crud = new JSONObject(true);
		JSONObject crudPost = new JSONObject(true);

		JSONObject crudAccessPost = new JSONObject(true);
		crudAccessPost.put("tag", "Access");
		crudPost.put("Access", crudAccessPost);

		JSONObject crudRequestPost = new JSONObject(true);
		crudRequestPost.put("tag", "Request[]");
		crudPost.put("Request[]", crudRequestPost);

		JSONArray request = new JSONArray();
		request.add(buildRequestPost);
		request.add(buildRequestBatchPost);
		request.add(buildRequestPutById);
		request.add(buildRequestBatchPutByIds);
		request.add(buildRequestDeleteByIds);
		request.add(buildDocumentRequestPost);
		request.add(buildDocumentRequestPutById);
		request.add(buildDocumentRequestDeleteByIds);
		request.add(buildDocumentRequestList);
		request.add(buildDocumentRequestDetail);

		JSONObject documentPost = buildDocument(table, RequestMethod.POST, 1,
				"/router/" + RequestMethod.POST.toString().toLowerCase() + "/" + urlSuffix);
		JSONObject documentPut = buildDocument(table, RequestMethod.PUT, 2,
				"/router/" + RequestMethod.PUT.toString().toLowerCase() + "/" + urlSuffix);
		JSONObject documentDelete = buildDocument(table, RequestMethod.DELETE, 3,
				"/router/" + RequestMethod.DELETE.toString().toLowerCase() + "/" + urlSuffix);
		JSONObject documentIndex = buildDocumentList(table,
				"/router/" + RequestMethod.GET.toString().toLowerCase() + "/" + urlSuffix + "list");
		JSONObject documentGetDetail = buildDocumentDetail(table,
				"/router/" + RequestMethod.GET.toString().toLowerCase() + "/" + urlSuffix);

		JSONArray document = new JSONArray();
		document.add(documentPost);
		document.add(documentPut);
		document.add(documentDelete);
		document.add(documentIndex);
		document.add(documentGetDetail);

		JSONObject crudDocumentPost = new JSONObject(true);
		crudDocumentPost.put("tag", "Document[]");
		crudPost.put("Document[]", crudDocumentPost);

		crud.put("@post", crudPost);
		crud.put("Access", accessPost);
		crud.put("Request[]", request);
		crud.put("Document[]", document);
		crud.put("format", true);
		crud.put("@explain", true);
		return crud;
	}

	public static JSONObject buildAccess(GenTable table) {
		String urlSuffix = VelocityUtils.getPermissionPrefix(table.getModuleName(), table.getBusinessName());
		// access参数: name,detail,appId
		JSONObject access = new JSONObject(true);
		access.put("get", "[\"UNKNOWN\", \"LOGIN\", \"CONTACT\", \"CIRCLE\", \"OWNER\", \"" + urlSuffix + ":query\",\""+ urlSuffix + ":list\"]");
		access.put("head", "[\"UNKNOWN\", \"LOGIN\", \"CONTACT\", \"CIRCLE\", \"OWNER\", \"" + urlSuffix + ":query\",\""+ urlSuffix + ":list\"]");
		access.put("gets", "[\"LOGIN\", \"OWNER\", \"" + urlSuffix + ":querys\"]");
		access.put("heads", "[\"LOGIN\", \"OWNER\", \"" + urlSuffix + ":querys\"]");
		access.put("post", "[\"LOGIN\", \"OWNER\",  \"" + urlSuffix + ":add\"]");
		access.put("put", "[\"LOGIN\", \"OWNER\",  \"" + urlSuffix + ":edit\"]");
		access.put("delete", "[\"LOGIN\", \"OWNER\", \"" + urlSuffix + ":remove\"]");
		access.put("name", capitalize(table.getTableName()));
		// access.put("appId", appId);
		return access;
	}

	public static JSONObject buildDocumentDetail(GenTable table, String url) throws IllegalAccessException {
		String capitalize = capitalize(table.getTableName());
		JSONObject document = new JSONObject(true);
		document.put("debug", 0);
		document.put("testAccountId", 0);
		document.put("name", "详情");
		document.put("version", 3);
		document.put("type", "JSON");
		document.put("request", "{}");
		document.put("url", url);

		JSONObject obj = new JSONObject(true);
		JSONObject objItem = new JSONObject(true);
		String column = "";
		for (GenTableColumn genTableColumn : table.getColumns()) {
			if (genTableColumn.isPk() == true) {
				obj.put("id@", capitalize + ":data." + genTableColumn.getColumnName());
			}

			if (genTableColumn.isEdit()) {
				column += genTableColumn.getColumnName() + ":" + genTableColumn.getJavaField() + ",";
			}
		}
		objItem.put("@column", column);
		obj.put(capitalize + ":data", objItem);
		obj.put("format", true);
		obj.put("@explain", true);
		log.info("查询json:{}", obj.toJSONString());
		document.put("apijson", obj.toString());
		return document;
	}

	private static String buildSearchColumn(GenTableColumn genTableColumn, String searchColumnName) {
		// 判断搜索方式
		 /** 查询方式（EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围） */
		switch(genTableColumn.getQueryType()) {
		case GenConstants.QUERY_NE:
			searchColumnName += "!";
			break;
		case GenConstants.QUERY_GT:
			searchColumnName += ">";
			break;
		case GenConstants.QUERY_GTE:
			searchColumnName += ">=";
			break;
		case GenConstants.QUERY_LT:
			searchColumnName += "<";
			break;
		case GenConstants.QUERY_LTE:
			searchColumnName += "<=";
			break;
		case GenConstants.QUERY_LIKE:
			searchColumnName += "~";
			break;
		case GenConstants.QUERY_BETWEEN:
			// 日期字段才行
			if(StringUtils.equals(genTableColumn.getHtmlType(), "datetime")) {
				searchColumnName += "%";
			}
			break;
		case GenConstants.QUERY_EQ:
		default:
			break;
		}
		return searchColumnName;
	}
	public static JSONObject buildDocumentList(GenTable table, String url) throws IllegalAccessException {
		String capitalize = capitalize(table.getTableName());
		JSONObject document = new JSONObject(true);
		document.put("debug", 0);
		document.put("testAccountId", 0);
		document.put("name", "列表");
		document.put("version", 3);
		document.put("type", "JSON");
		document.put("request", "{}");
		document.put("url", url);

		JSONObject obj = new JSONObject(true);
		// 创建人, 支持管理员和普通用户查询
		// 使用创建人，请将 主键 和 UserId填写为不一样
		boolean isCreateBy = false;
		if(StringUtils.isNoneBlank(table.getUserId())) {
			for (GenTableColumn genTableColumn : table.getColumns()) {
				if (genTableColumn.isPk() == true && StringUtils.equals(table.getUserId(), genTableColumn.getColumnName()) == false) {
					// "id@-()": "getCurrentUserIdOrAdmin(id@-(),Ordermaster:rows[].Ordermaster.customerNo@)",
					String createByKey = table.getUserId()+"@-()";
					obj.put(createByKey, "getCurrentUserIdOrAdmin("+createByKey+","+capitalize + ":rows[]"+"."+capitalize+"."+table.getUserId()+"@)");
					isCreateBy = true;
					break;
				}
			}
		}
				
		String combine = "";
		for (GenTableColumn genTableColumn : table.getColumns()) {
			if (genTableColumn.isQuery()) {
				String searchColumnName = buildSearchColumn(genTableColumn, genTableColumn.getColumnName());
				obj.put(genTableColumn.getJavaField() + "@", capitalize + ":rows[]." + capitalize + "." + searchColumnName);
				if (genTableColumn.isPk() == false && (StringUtils.equals(table.getUserId(), genTableColumn.getColumnName()) == false)) {
					combine += searchColumnName + ":1=1 & ";
				}
			}
		}
		obj.put("pageNum@", capitalize + ":rows[].page");
		obj.put("pageSize@", capitalize + ":rows[].count");
		JSONObject objItem = new JSONObject(true);
		JSONObject tableItem = new JSONObject(true);
		if(isCreateBy) {
			tableItem.put(table.getUserId()+"@", table.getUserId());
		}
		String column = "";
		for (GenTableColumn genTableColumn : table.getColumns()) {
			if (genTableColumn.isList()) {
				column += genTableColumn.getColumnName() + ":" + genTableColumn.getJavaField() + ",";
			}
		}
		tableItem.put("@column", column);
		if (combine.length() > 0) {
			tableItem.put("@combine",
					combine = combine.endsWith(" & ") ? combine.substring(0, combine.length() - 3) : combine);
		}
		
		objItem.put("query", 2);
		objItem.put(capitalize, tableItem);
		obj.put(capitalize + ":rows[]", objItem);
		obj.put("total@", "/" + capitalize + ":rows[]/total");
		obj.put("format", true);
		obj.put("@explain", true);
		log.info("查询json:{}", obj.toJSONString());
		document.put("apijson", obj.toString());
		return document;
	}

	public static JSONObject buildDocument(GenTable table, RequestMethod method, Integer optionType, String url)
			throws IllegalAccessException {
		String capitalize = capitalize(table.getTableName());
		JSONObject document = new JSONObject(true);
		document.put("debug", 0);
		document.put("testAccountId", 0);
		document.put("name", "接口名称"); // 接口名称
		document.put("version", 3);
		document.put("type", "JSON");
		document.put("request", "{}");

		JSONObject json = new JSONObject(true);
		switch (optionType) {
		case 1: // 单表插入
			document.put("name", "新增");
			for (GenTableColumn genTableColumn : table.getColumns()) {
				if (genTableColumn.isInsert()) {
					json.put(genTableColumn.getJavaField() + "@", capitalize + "." + genTableColumn.getColumnName());
				}
			}
			break;
		case 2: // id修改
			document.put("name", "修改");
			for (GenTableColumn genTableColumn : table.getColumns()) {
				if (genTableColumn.isEdit()) {
					json.put(genTableColumn.getJavaField() + "@", capitalize + "." + genTableColumn.getColumnName());
				}
			}
			break;
		case 3: // ids删除
			document.put("name", "删除");
			for (GenTableColumn genTableColumn : table.getColumns()) {
				if (genTableColumn.isPk() == true) {
					json.put("ids@",
							capitalize + "." + genTableColumn.getColumnName() + "{}");
					break;
				}
			}
			break;
		default:
			break;
		}

		// 生成json
		json.put("tag", capitalize);
		json.put(capitalize, new JSONObject(true));
		json.put("format", true);
		json.put("@explain", true);
		document.put("apijson", json.toString());
		document.put("url", url);
		return document;
	}

	public static JSONObject buildRequestDetail(GenTable table, String tag) {
		// 单条新增
		JSONObject requestItem_post = new JSONObject(true);
		requestItem_post.put("method", RequestMethod.GET.name());
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		requestItem_post.put("tag", tag);
		requestItem_post.put("detail", "列表");
		// requestItem_post.put("appId", appId);
		JSONObject requestItem_structure = new JSONObject(true);
		requestItem_structure.put("MUST", "id"); // 必传字段
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("INSERT", option); // 角色等配置
		requestItem_post.put("structure", requestItem_structure.toString());
		return requestItem_post;
	}

	public static JSONObject buildRequestList(GenTable table, String tag) {
		// 单条新增
		JSONObject requestItem_post = new JSONObject(true);
		requestItem_post.put("method", RequestMethod.GET.name());
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		requestItem_post.put("tag", tag);
		requestItem_post.put("detail", "列表");
		// requestItem_post.put("appId", appId);
		JSONObject requestItem_structure = new JSONObject(true);
		requestItem_structure.put("MUST", "pageNum,pageSize"); // 必传字段
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("INSERT", option); // 角色等配置
		requestItem_post.put("structure", requestItem_structure.toString());
		return requestItem_post;
	}

	public static JSONObject buildRequestPost(GenTable table, String tag) {
		// 单条新增
		JSONObject requestItem_post = new JSONObject(true);
		requestItem_post.put("method", RequestMethod.POST.name());
		boolean isRouterRequest = tag == null ? false : true;
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		requestItem_post.put("tag", tag);
		requestItem_post.put("detail", "新增");
		// requestItem_post.put("appId", appId);
		JSONObject requestItem_structure = new JSONObject(true);
		String must = "";
		for (GenTableColumn genTableColumn : table.getColumns()) {
			if (genTableColumn.isRequired()) {
				if (isRouterRequest) {
					must += genTableColumn.getJavaField() + ",";
				} else {
					must += genTableColumn.getColumnName() + ",";
				}
			}
		}

		if (StringUtils.isNotBlank(must)) {
			requestItem_structure.put("MUST", must); // 必传字段
		}
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("INSERT", option); // 角色等配置
		if (table.getPkColumn() != null && table.getPkColumn().isIncrement() == false) {
			// TODO 暂时去掉， SmarterFramework框架会传递idd字段
			// requestItem_structure.put("REFUSE", table.getPkColumn().getJavaField());
		}
		requestItem_post.put("structure", requestItem_structure.toString());

		// 生成router配置

		return requestItem_post;
	}

	public static JSONObject buildRequestBatchPost(GenTable table, String tag) {
		JSONObject request_mul_post = new JSONObject(true);
		request_mul_post.put("method", RequestMethod.POST.name());
		boolean isRouterRequest = tag == null ? false : true;
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		request_mul_post.put("tag", tag + "[]");
		request_mul_post.put("detail", "批量新增");
		// request_mul_post.put("appId", appId);

		JSONObject requestItem_structure = new JSONObject(true);
		String must = "";
		for (GenTableColumn genTableColumn : table.getColumns()) {
			if (genTableColumn.isRequired()) {
				if (isRouterRequest) {
					must += genTableColumn.getJavaField() + ",";
				} else {
					must += genTableColumn.getColumnName() + ",";
				}
			}
		}
		if (StringUtils.isNotBlank(must)) {
			requestItem_structure.put("MUST", must); // 必传字段
		}
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("INSERT", option); // 角色等配置
		if (table.getPkColumn() != null && table.getPkColumn().isIncrement() == false) {
			//requestItem_structure.put("REFUSE", table.getPkColumn().getJavaField());
		}

		JSONArray requestItem_structure_array_item = new JSONArray();
		requestItem_structure_array_item.add(requestItem_structure);
		JSONObject request_structure_array = new JSONObject(true);
		request_structure_array.put(capitalize(table.getTableName()) + "[]", requestItem_structure_array_item);
		request_mul_post.put("structure", request_structure_array.toString());
		return request_mul_post;
	}

	public static JSONObject buildRequestPutById(GenTable table, String tag) throws IllegalAccessException {
		JSONObject requestItem_put = new JSONObject(true);
		requestItem_put.put("method", RequestMethod.PUT.name());
		boolean isRouterRequest = tag == null ? false : true;
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		requestItem_put.put("tag", tag);
		requestItem_put.put("detail", "id修改");
		// requestItem_put.put("appId", appId);
		JSONObject requestItem_structure = new JSONObject(true);
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("UPDATE", option); // 角色等配置
		if (table.getPkColumn() != null) {
			if (isRouterRequest) {
				requestItem_structure.put("MUST", table.getPkColumn().getJavaField()); // 必传字段
			} else {
				requestItem_structure.put("MUST", table.getPkColumn().getColumnName()); // 必传字段
			}
		} else {
			throw new IllegalAccessException("主键是必传参数!");
		}
		requestItem_put.put("structure", requestItem_structure.toString());
		return requestItem_put;
	}

	public static JSONObject buildRequestBatchPutByIds(GenTable table, String tag) throws IllegalAccessException {
		JSONObject request_mul_put = new JSONObject(true);
		request_mul_put.put("method", RequestMethod.PUT.name());
		boolean isRouterRequest = tag == null ? false : true;
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		request_mul_put.put("tag", tag + "[]");
		request_mul_put.put("detail", "批量修改");
		// request_mul_put.put("appId", appId);

		JSONObject requestItem_structure = new JSONObject(true);
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("UPDATE", option); // 角色等配置
		if (table.getPkColumn() != null) {
			if (isRouterRequest) {
				requestItem_structure.put("MUST", table.getPkColumn().getJavaField()); // 必传字段
			} else {
				requestItem_structure.put("MUST", table.getPkColumn().getColumnName()); // 必传字段
			}
		} else {
			throw new IllegalAccessException("主键是必传参数!");
		}

		JSONArray requestItem_structure_array_item = new JSONArray();
		requestItem_structure_array_item.add(requestItem_structure);
		JSONObject request_structure_array = new JSONObject(true);
		request_structure_array.put(capitalize(table.getTableName()) + "[]", requestItem_structure_array_item);
		request_mul_put.put("structure", request_structure_array.toString());
		return request_mul_put;
	}

	public static JSONObject buildRequestDeleteByIds(GenTable table, String tag) throws IllegalAccessException {
		JSONObject requestItem_delete = new JSONObject(true);
		requestItem_delete.put("method", RequestMethod.DELETE.name());
		boolean isRouterRequest = tag == null ? false : true;
		tag = tag == null ? capitalize(table.getTableName()) : tag;
		requestItem_delete.put("tag", tag);
		requestItem_delete.put("detail", "ids删除");
		// requestItem_delete.put("appId", appId);
		JSONObject requestItem_structure = new JSONObject(true);
		if (table.getPkColumn() != null) {
			if (isRouterRequest) {
				requestItem_structure.put("MUST", "ids"); // 必传字段
			} else {
				requestItem_structure.put("MUST", table.getPkColumn().getColumnName() + "{}"); // 必传字段
			}
		} else {
			throw new IllegalAccessException("主键是必传参数!");
		}
		JSONObject option = new JSONObject(true);
		option.put("@role", "LOGIN,OWNER");
		requestItem_structure.put("INSERT", option); // 角色等配置
		requestItem_structure.put("REFUSE", "!");
		requestItem_delete.put("structure", requestItem_structure.toString());
		return requestItem_delete;
	}

	public static String capitalize(String str) {
		if (str == null || str.length() == 0) {
			return str;
		}
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}

	public static JSONObject generatorCodeFunction(String request, HttpSession session) throws Exception {
		JSONObject functionRequest = JSONObject.parseObject(request);
		JSONObject json = new JSONObject(true);
		JSONObject function = new JSONObject(true);
		function.put("debug", 0);
		function.put("type", 0);
		function.put("name", functionRequest.getString("name"));
		function.put("returnType", functionRequest.getString("returnType"));
		function.put("arguments", functionRequest.getString("arguments"));
		function.put("demo", functionRequest.getString("demo"));
		function.put("detail", functionRequest.getString("detail"));

		json.put("Function", function);
		json.put("tag", "Function");
		json.put("format", true);
		json.put("@explain", true);

		JSONObject response = new FormParser(RequestMethod.POST).setSession(session).setNeedVerify(true)
				.parseResponse(json);
		log.info("generatorCodeFunction response:{}", response);

		// 增量初始化Function
		if (response.getInteger("code") == 200) {
			ApijsonInitUtil.addInitFunction(response.getJSONObject("function").getLong("id"));
		}
		return response;
	}
	

	public static <E extends Enum<E>> E getEnum(final Class<E> enumClass, final String enumName, final E defaultEnum) {
        if (enumName == null) {
            return defaultEnum;
        }
        try {
            return Enum.valueOf(enumClass, enumName);
        } catch (final IllegalArgumentException ex) {
            return defaultEnum;
        }
    }
	
	public static JSONObject generatorCodeJSON(String request, HttpSession session) throws Exception {
		JSONObject requestJson = JSONObject.parseObject(request);
		String urlSuffix = requestJson.getString("urlSuffix"); // url前缀必须以英文大写字母开头
		if(urlSuffix == null || Character.isUpperCase(urlSuffix.charAt(0)) == false) {
			throw new IllegalArgumentException("url前缀必须以英文大写字母开头！");
		}
		urlSuffix = urlSuffix + String.valueOf(System.currentTimeMillis());
		String method = requestJson.getString("method");
		if (getEnum(RequestMethod.class, method.toUpperCase(), null) == null) {
			throw new IllegalArgumentException("method:{"+method+"}参数传递不正确！");
		}
		
		String url = "/router/" + method.toLowerCase() + "/" + urlSuffix;
		JSONObject crud = generatorCodeJSON(url, urlSuffix, requestJson, session);
		JSONObject response = new FormParser(RequestMethod.CRUD).setSession(session).setNeedVerify(true)
				.parseResponse(crud);
		log.info("generatorCodeJSON response:{}", response);
		// 增量初始化配置
		if (response.getInteger("code") == 200) {
			ApijsonInitUtil.addInitRequest(response.getJSONObject("request").getLong("id"));
			ApijsonInitUtil.addInitDocument(response.getJSONObject("document").getLong("id"));
		}
		response.put("url", url);
		return response;
	}
}
