package cn.myapps.runtime.dynaform.view.controller;

import cn.myapps.authtime.privilege.operation.model.OperationVO;
import cn.myapps.common.Environment;
import cn.myapps.common.auth.IUser;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.data.DataPackage;
import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.model.activity.Activity;
import cn.myapps.common.model.activity.ActivityType;
import cn.myapps.common.model.permission.Permission;
import cn.myapps.common.model.view.AbstractView;
import cn.myapps.common.model.view.Column;
import cn.myapps.common.model.view.TreeView;
import cn.myapps.common.model.view.constant.ViewConstant;
import cn.myapps.common.model.view.type.TreeType;
import cn.myapps.common.util.StringUtil;
import cn.myapps.common.util.cache.MemoryCacheUtil;
import cn.myapps.designtime.common.service.DesignTimeServiceManager;
import cn.myapps.designtime.permission.PermissionUtil;
import cn.myapps.designtime.view.service.ViewDesignTimeService;
import cn.myapps.runtime.common.controller.AbstractRuntimeController;
import cn.myapps.runtime.common.service.RunTimeServiceManager;
import cn.myapps.runtime.dynaform.PermissionType;
import cn.myapps.runtime.dynaform.document.ejb.Document;
import cn.myapps.runtime.dynaform.document.ejb.DocumentProcess;
import cn.myapps.runtime.dynaform.form.ejb.*;
import cn.myapps.runtime.dynaform.view.tree.DocumentTree;
import cn.myapps.runtime.logger.service.LogHelper;
import cn.myapps.runtime.macro.runner.IRunner;
import cn.myapps.runtime.macro.runner.JavaScriptFactory;
import cn.myapps.util.DateUtil;
import cn.myapps.util.property.MultiLanguageProperty;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bcxin.components.TenantContext;
import com.bcxin.saas.core.exceptions.SaasNofoundException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.*;

/**
 * View Restful 接口
 *
 * @author ahan
 *
 */
@Api(tags = "视图执行模块")
@Component
@RequestMapping(path = "/api/runtime/{applicationId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class ViewController extends AbstractRuntimeController {

	@Autowired
	private ViewDesignTimeService viewService;

	/**
	 * 获取视图模板
	 * @param applicationId 软件id
	 * @param id 视图id
	 * @param parentId 父id
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	@GetMapping(path = "/views/{id}/template")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取视图模板", notes = "获取视图模板")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "parentId",value = "父Id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "isRelate",value = "isRelate",required = false,paramType = "query",dataType = "string")
	})
	public Resource doGetView(@PathVariable String applicationId,
							  @PathVariable String id,
							  @RequestParam(required = false) String parentId,
							  @RequestParam(required = false) String isRelate) throws Exception {
		ParamsTable params = getParams();

		if ("true".equals(isRelate)) {
			params.setParameter("parentid", parentId);
			params.setParameter("relateid", parentId);
		} else {
			params.setParameter("relateid", parentId);
		}

		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView tempView = vProcess.doView(id);
		if (tempView == null) {
			String error = String.format("doGetView找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}

		AbstractView view = (AbstractView) BeanUtils.cloneBean(tempView);
		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(view.getApplicationid());
			if (view instanceof TreeView) {
				try {
					params.setParameter("treedocid", parentId);
					params.setParameter("parentNodeId", parentId);

					TreeView.LinkVO link = ((TreeView) view).getLink();
					if (link != null) {
						((TreeView) view).setLinkViewId(link.getActionContent());
					}
				} catch (Exception e) {
				}
			}

			DocumentProcess dProcess = RunTimeServiceManager.documentProcess(applicationId);

			Document tdoc = null;
			Document parent = null;
			if (StringUtil.isBlank(parentId)) {
				tdoc = new Document();
			} else {
				parent = (Document) dProcess.doView(parentId);
				tdoc = parent != null ? parent : new Document();
			}

			IRunner runner = JavaScriptFactory.getInstance(getUser().getSessionid(), applicationId);
			runner.initBSFManager(tdoc, params, getUser(), new ArrayList<ValidateMessage>());

			List<Activity> activitys = view.getActivities();
			if (activitys != null) {
				List<Activity> result = new ArrayList<Activity>();
				for (Iterator<Activity> iterator = activitys.iterator(); iterator.hasNext(); ) {
					Activity act = Activity.clone(iterator.next());
					//当按钮的标签不为空时，前台显示的按钮名称为改按钮的标签名
					String label = getActivityLabel(view.getFullName(), act, runner);
					if (!StringUtil.isBlank(label)) {
						act.setName(label);
					}
					boolean hidden = act.isHidden(runner, view, tdoc, getUser(), Permission.VIEW_TYPE);
					if (!hidden) {
						//多语言设置
						String multiLanguageLabel = act.getMultiLanguageLabel();
						if (!StringUtil.isBlank(multiLanguageLabel)) {
							String multiLangTag = act.getName();
							String labelHex = URLEncoder.encode(multiLanguageLabel, "utf-8");
							String nameHex = URLEncoder.encode(multiLangTag, "utf-8");
							multiLangTag = "{*[" + labelHex + "^" + nameHex + "^true]*}";
							act.setName(multiLangTag);
						}

						boolean readonly = act.isReadonly(runner, view.getFullName());
						act.setReadonly(readonly);
					}
					//判断主表单是否归档
					if (parent != null) {
						//归档后没有流程实例（子流程实例和主流程实例都会被删除）
						boolean isparentArchive = !StringUtil.isBlank(parent.getStateid()) && parent.getState() == null ? true : false;
						boolean isReadOperate = false;
						if (act.getType() == ActivityType.EXPTOEXCEL ||
								act.getType() == ActivityType.DOCUMENT_QUERY ||
								act.getType() == ActivityType.FILE_DOWNLOAD ||
								act.getType() == ActivityType.PRINT_VIEW) {
							isReadOperate = true;
						}
						if ((!hidden && !isparentArchive) || (!hidden && isparentArchive && isReadOperate)) {
							result.add(act);
						}
					} else {
						if (!hidden) {
							result.add(act);
						}
					}
				}
				view.setActivities(result);
			}

			List<Column> columns = view.getColumns();
			if (columns != null) {
				List<Column> result = new ArrayList<Column>();
				for (Iterator<Column> iterator = columns.iterator(); iterator.hasNext(); ) {
					Column column = Column.clone(iterator.next());
					boolean isHidden = false;
					if (!StringUtil.isBlank(column.getHiddenScript())) {
						isHidden = column.isHiddenColumn(runner);
						column.setHiddenColumn(isHidden);
					}
					if (column.getFormField() != null) {
						column.setColumnField(column.getFormField().getClass().getSimpleName());
						column.setFieldId(column.getFormField().getId());
					}
					if (!isHidden) {
						if (!StringUtil.isBlank(column.getMultiLanguageLabel())) {
							String text = getPropertyByMultiLanguage(request, applicationId, column.getMultiLanguageLabel(), column.getName());
							column.setName(text);
						}
						String iconMapping = column.getIconMapping();//为了前端方便，此处把iconMapping写成json格式给前端调用
						if (!StringUtil.isBlank(iconMapping) && !iconMapping.contains("value") && !iconMapping.contains("key")) {
							String[] icons = column.getIconMapping().split(";");
							JSONArray jsonArray = new JSONArray();
							for (String icon : icons) {
								String[] iconKeyAndValue = icon.split(":");
								JSONObject jsonObject = new JSONObject();
								jsonObject.put("key", iconKeyAndValue[0]);
								jsonObject.put("value", iconKeyAndValue[1]);
								jsonArray.add(jsonObject);
							}
							column.setIconMapping(jsonArray.toJSONString());
						}
					}
					result.add(column);
				}
				view.setColumns(result);
			}
			if (view.getShowWaterMark()) {
				String waterMake = (String) runner.run(view, "view:" + view.getName() + "-" + view.getId() + ".waterMarkScript", view.getWaterMarkScript());
				view.setWaterMarkText(waterMake);
				;
			}
			if (view.getOpenType() == ViewConstant.OPEN_TYPE_GRID && view.getViewTypeImpl().intValue() == ViewConstant.VIEW_TYPE_NORMAL) {
				boolean editable = true;
				boolean readonly = true;
				if (!StringUtil.isBlank(view.getEditableScript())) {
					editable = (boolean) runner.run(view, "view:" + view.getName() + "-" + view.getId() + ".editableScript", view.getEditableScript());
				}
				if (!StringUtil.isBlank(view.getReadonlyScript())) {
					readonly = (boolean) runner.run(view, "view:" + view.getName() + "-" + view.getId() + ".readonlyScript", view.getReadonlyScript());
				}
				view.setEditAble(editable);
				view.setReadAble(readonly);
			}
			return success("ok", view);
		} finally {
			context.reset();
		}
	}

	/**
	 * 获取视图
	 * @param applicationId 软件id
	 * @param id 视图id
	 * @param parentId 父id
	 * @param sortCol 排序列字段
	 * @param sortStatus 排序状态(升序DESC或降序ASC)
	 * @param lines 每页显示数
	 * @param content 请求包体
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	@PostMapping(path = "/views/{id}/documents")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取视图", notes = "获取视图")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "parentId",value = "父Id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "startDate",value = "日历视图开始时间",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "endDate",value = "日历视图结束时间",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "sortCol",value = "排序列字段",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "sortStatus",value = "排序状态(升序DESC或降序ASC)",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "parentParam",value = "折叠视图的上级参数",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "lines",value = "每页显示数",required = false,paramType = "query",dataType = "string",defaultValue="5"),
			@ApiImplicitParam(name = "isQueryButton",value = "是否查询按钮",required = false,paramType = "query",dataType = "boolean"),
			@ApiImplicitParam(name = "content",value = "请求包体",required = false,paramType = "body",dataType = "string")
	})
	public Resource doGetDocuments(@PathVariable String applicationId,
								   @PathVariable String id,
								   @RequestParam(required = false) String parentId,
								   @RequestParam(required = false) String isRelate,
								   @RequestParam(required = false) String startDate,
								   @RequestParam(required = false) String endDate,
								   @RequestParam(required = false) String sortCol,
								   @RequestParam(required = false) String sortStatus,
								   @RequestParam(required = false) String parentParam,
								   @RequestParam(required = false,defaultValue="10") String lines,
								   @RequestParam(required = false, defaultValue = "false") boolean isQueryButton,
								   @RequestBody(required=false) String content) throws Exception {

		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(id);
		if (view == null) {
			String error = String.format("doGetDocuments找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}
		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(view.getApplicationid());
			ParamsTable params = getParams(); // 获取并设置参数
			IUser user = getUser();
			Document searchDocument = null;
			DataPackage<Document> dataPackage = null;
			Collection<Document> data = null;

			if (!StringUtil.isBlank(content)) {
				JSONObject jsonObject = JSONObject.parseObject(content);
				for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					params.setParameter(key, value);
				}
			}

			if (view.getSearchForm() != null) {
				Form searchForm = view.getSearchForm();
				searchDocument = searchForm.createDocument(params, user);

				IRunner runner = JavaScriptFactory.getInstance(session.getId(), view.getApplicationid());
				runner.initBSFManager(searchDocument, params, user, new ArrayList<ValidateMessage>());
				for (Map.Entry<String, Object> entry : searchDocument.getItemMap().entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					if (value instanceof Date) {
						FormField filed = searchForm.findFieldByName(key);
						//此处会把params里面有的字段且为时间格式的话，会转成国际标准，需要格式化
						if (filed != null && filed instanceof DateField) {

							value = DateUtil.format((Date) value, ((DateField) filed).getDatePatternValue());
						} else {
							value = DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss");
						}
					} else {
						FormField filed = searchForm.findFieldByName(key);
						//处理下拉框没有默认值问题
						if ((value == null || value.equals("")) && filed != null && filed instanceof SelectField) {
							((SelectField) filed).getOptions(runner, searchDocument, user);
							value = searchDocument.getItemValueAsString(key);
						}
					}
					if (value != null) {
						params.setParameter(key, value);
					}
				}
			} else {
				searchDocument = new Document();
			}
			if ("true".equals(isRelate)) {
				params.setParameter("parentid", parentId);
				params.setParameter("relateid", parentId);
			} else {
				params.removeParameter("parentId");
				params.removeParameter("parentid");
				params.setParameter("relateid", parentId);
			}
			params.setParameter("refreshparent", true);
			params.setParameter("isedit", false);
			params.setParameter("lines", lines);
			params.setParameter("startDate", startDate);
			params.setParameter("endDate", endDate);
			params.setParameter("_viewid", id);
			params.setParameter("isQueryButton", isQueryButton);

			// 根据列进行视图排序
			if (!StringUtil.isBlank(sortCol)) {
				List<String> colFieldsList = new ArrayList<String>();
				String fieldName = view.getFormFieldNameByColsName(sortCol);
				if (!StringUtil.isBlank(fieldName)) {
					colFieldsList.add(fieldName + " " + sortStatus);
					params.setParameter("_sortCol", colFieldsList.toArray(new String[colFieldsList.size()]));
				}
			} else {
				params.setParameter("_sortCol", view.getDefaultOrderFieldArr());
			}

			if ("TreeView".equalsIgnoreCase(view.getSimpleClassName())
					/*	||"CalendarView".equalsIgnoreCase(view.getSimpleClassName())*/
					|| "MapView".equalsIgnoreCase(view.getSimpleClassName())) {
				params.setParameter("lines", Integer.MAX_VALUE);
			}

			dataPackage = view.getViewTypeImpl().getViewDatas(
					params, getUser(),
					searchDocument);
			data = dataPackage.getDatas();

			Map<String, Object> cache = new HashMap<String, Object>();

			List<Map<String, Object>> result = viewService
					.manipulationDocumentDatas2ViewDatas(data, view, params,
							getUser(), parentParam, cache);


			int page = dataPackage.getPageNo();
			int page_lines = dataPackage.getLinesPerPage();
			int row_count = dataPackage.getRowCount();
			//查询是否有子节点
			if ("CollapsibleView".equalsIgnoreCase(view.getSimpleClassName())) {
				row_count = result.size();
				Iterator<Map<String, Object>> iterator = result.iterator();
				while (iterator.hasNext()) {
					Map<String, Object> map = iterator.next();
					String parentName = (String) map.get("parentName") + "\\";

					List<Map<String, Object>> subResult = viewService
							.manipulationDocumentDatas2ViewDatas(data, view, params,
									getUser(), parentName, cache);
					if (subResult.isEmpty()) {
						map.put("hasChild", false);
					} else {
						map.put("hasChild", true);
					}
				}
			}

			//判断视图是否开启小计总计功能
			if (view.isSum()) {
				IRunner runner = null;
				if (runner == null) { //hotfix : runner为空时，重新构建
					Document parent = (Document) request.getAttribute("parent");
					Document tdoc = parent != null ? parent : new Document();
					runner = JavaScriptFactory.getInstance(
							user.getSessionid(), view.getApplicationid());
					runner.initBSFManager(tdoc, params, user,
							new ArrayList<ValidateMessage>());
				}

				Map<String, Object> sumItems = new HashMap<String, Object>();
				Map<String, Object> totalItems = new HashMap<String, Object>();
				int sumCount = 0;
				int totalCount = 0;
				for (Iterator<Column> iterator = view.getColumns().iterator(); iterator.hasNext(); ) {
					Column column = iterator.next();
					StringBuffer sumSb = new StringBuffer();
					StringBuffer totalSb = new StringBuffer();

					if (column.isSum()) {
						sumSb.append(column.getSumByDatas(dataPackage, runner, user));
						sumCount++;

						Map<String, Object> map = new HashMap<String, Object>();
						map.put("name", column.getName());
						map.put("fieldtype", "VALUE_TYPE_SUM");
						map.put("value", sumSb.toString());
						sumItems.put(column.getId(), map);
					}
					//总计功能支持设计模式和SQL模式
					if ((view.getEditMode().equals(ViewConstant.EDIT_MODE_DESIGN) || view.getEditMode().equals(ViewConstant.EDIT_MODE_CODE_SQL)) && column.isTotal()) {
						totalSb.append(column.getSumTotal(user,
								user.getDomainid(), params));
						totalCount++;

						Map<String, Object> map = new HashMap<String, Object>();
						map.put("name", column.getName());
						map.put("fieldtype", "VALUE_TYPE_SUM");
						map.put("value", totalSb.toString());
						totalItems.put(column.getId(), map);
					}
				}
				if (sumCount > 0) {
					Map<String, Object> sumLine = new HashMap<String, Object>();
					sumLine.put("isSum", true);
					sumLine.put("items", sumItems);
					result.add(sumLine);
				}
				if (totalCount > 0) {
					Map<String, Object> totalLine = new HashMap<String, Object>();
					totalLine.put("isTotal", true);
					totalLine.put("items", totalItems);
					result.add(totalLine);
				}
			}
			//查询时记录日志
			if (isQueryButton) {
				String description = view.getDescription();
				if (StringUtil.isBlank(description)) {
					description = view.getFullName();
				}
				LogHelper.saveLogByDyAction("列表查询", "视图-" + description, user, request);
			}

			Resource resource = successWithPagination("ok", result, page, page_lines, row_count);

			return resource;
		} finally {
			context.reset();
		}
	}

	/**
	 * 获取树形视图数据
	 * @param applicationId 软件id
	 * @param id 视图id
	 * @param parentId 父id
	 * @param sortCol 排序列字段
	 * @param sortStatus 排序状态(升序DESC或降序ASC)
	 * @param lines 每页显示数
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	@PostMapping(path = "/treeviews/{id}/documents")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取树形视图数据", notes = "获取树形视图数据")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "parentId",value = "父id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "name",value = "本节点名称",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "content",value = "请求包体",required = true,paramType = "body",dataType = "string"),
			@ApiImplicitParam(name = "isQueryButton",value = "是否查询按钮",required = false,paramType = "query",dataType = "boolean")
	})
	public Resource doGetTreeDocuments(@PathVariable String applicationId,
									   @PathVariable String id,
									   @RequestParam(required = false) String parentId,
									   @RequestParam(required = false) String name,
									   @RequestBody String content,
									   @RequestParam(required = false, defaultValue = "false") boolean isQueryButton) throws Exception {

		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(id);
		if (view == null) {
			String error = String.format("doGetTreeDocuments找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}
		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(view.getApplicationid());
			ParamsTable params = getParams(); // 获取并设置参数
			IUser user = getUser();
			Document searchDocument = null;
			DataPackage<Document> dataPackage = null;
			Collection<Document> data = null;

			if (!StringUtil.isBlank(content)) {
				JSONObject jsonObject = JSONObject.parseObject(content);
				for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					params.setParameter(key, value);
				}
			}

			String parentDocId = params.getParameterAsString("parentDocId");
			if (!StringUtil.isBlank(parentDocId)) {
				params.setParameter("relateId", parentDocId);
			}

			if (view.getSearchForm() != null) {
				Form searchForm = view.getSearchForm();
				searchDocument = searchForm.createDocument(params, user);

				IRunner runner = JavaScriptFactory.getInstance(session.getId(), view.getApplicationid());
				runner.initBSFManager(searchDocument, params, user, new ArrayList<ValidateMessage>());
				for (Map.Entry<String, Object> entry : searchDocument.getItemMap().entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					if (value instanceof Date) {
						FormField filed = searchForm.findFieldByName(key);
						//此处会把params里面有的字段且为时间格式的话，会转成国际标准，需要格式化
						if (filed != null && filed instanceof DateField) {

							value = DateUtil.format((Date) value, ((DateField) filed).getDatePatternValue());
						} else {
							value = DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss");
						}
					} else {
						FormField filed = searchForm.findFieldByName(key);
						//处理下拉框没有默认值问题
						if ((value == null || value.equals("")) && filed != null && filed instanceof SelectField) {
							((SelectField) filed).getOptions(runner, searchDocument, user);
							value = searchDocument.getItemValueAsString(key);
						}
					}
					if (value != null) {
						params.setParameter(key, value);
					}
				}
			} else {
				searchDocument = new Document();
			}
			params.setParameter("refreshparent", true);
			params.setParameter("isedit", false);
			params.setParameter("isRelate", true);
			//树形视图数据参数
			//		params.setParameter("parentNodeId", parentId);
//		params.setParameter("treedocid", parentId);
			params.setParameter("_docid", parentId);
			// 根据列进行视图排序
			params.setParameter("_sortCol", view.getDefaultOrderFieldArr());


			if (StringUtil.isBlank(name)) {
				dataPackage = view.getViewTypeImpl().getViewDatas(params, getUser(), searchDocument);
			} else {
				TreeType treeType = (TreeType) view.getViewTypeImpl();
				dataPackage = treeType.getViewDatasByName(params, name, user, searchDocument);
			}
			data = dataPackage.getDatas();

			List<Map<String, Object>> result = viewService
					.manipulationDocumentDatas2ViewDatas(data, view, params,
							getUser(), "", new HashMap<String, Object>());

			int page = dataPackage.getPageNo();
			int page_lines = dataPackage.getLinesPerPage();
			int row_count = dataPackage.getRowCount();
			//查询时记录日志
			if (isQueryButton) {
				String description = view.getDescription();
				if (StringUtil.isBlank(description)) {
					description = view.getFullName();
				}
				LogHelper.saveLogByDyAction("列表查询", "视图-" + description, user, request);
			}
			return successWithPagination("ok", result, page, page_lines, row_count);
		} finally {
			context.reset();
		}
	}

	/**
	 * 获取查询表单模板
	 * @param applicationId 表单id
	 * @param id 视图id
	 * @return
	 * @throws Exception
	 */
	@GetMapping(path = "/views/{id}/searchformtemplate")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取查询表单模板", notes = "获取查询表单模板")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string")
	})
	public Resource getSearchFormTemplate(@PathVariable String applicationId,
										  @PathVariable String id) throws Exception {
		IUser user = getUser();
		ParamsTable params = getParams();
		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(id);
		if (view == null) {
			String error = String.format("getSearchFormTemplate找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}

		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(view.getApplicationid());
			IRunner runner = JavaScriptFactory.getInstance(user.getSessionid(), applicationId);
			Document searchDocument = null;
			if (view.getSearchForm() != null) {
				searchDocument = view.getSearchForm().createDocument(params, getUser());
			} else {
				searchDocument = new Document();
			}
			Map<String, Object> map = new HashMap<String, Object>();

			StringBuilder buffer = new StringBuilder();
			StringBuilder template = new StringBuilder();
			Form form = searchDocument.getForm();

			String formId = form == null ? "" : form.getId();

			List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
			if (form != null) {
				template.append(form.getHtmlTemplate(searchDocument, runner, user));
				buffer.append(template.toString());
				buffer.append("<input type=\"hidden\" id=\"dy_refreshObj\" formid=\"" + formId + "\"");
				buffer.append(" docid=\"" + searchDocument.getId() + "\" userid=\"" + user.getId() + "\"");
				buffer.append(" mapVal=\"");
				for (Iterator<FormField> iter = form.getAllFields().iterator(); iter.hasNext(); ) {
					Object obj = iter.next();
					if (obj instanceof ValueStoreField) {
						FormField field = (FormField) obj;
						buffer.append(field.getName() + ";");
					}
				}
				if (buffer.lastIndexOf(";") != -1) {
					buffer.deleteCharAt(buffer.lastIndexOf(";"));
				}
				Collection<FormField> fields = form.getFields();
				for (FormField formField : fields) {
					Map<String, Object> value = formField.toAttributes(searchDocument, runner, getUser(), PermissionType.MODIFY);
					//表单编辑器自定义的属性
					if (formField.getOtherPropsAsMap() != null && value != null && !value.isEmpty()) {
						for (String propertyKey : formField.getOtherPropsAsMap().keySet()) {
							if (value.get(propertyKey) == null) {
								value.put(propertyKey, formField.getOtherPropsAsMap().get(propertyKey));
							}
						}
					}
					data.add(value);
				}
				buffer.append("\" />");
			}

			map.put("fields", data);
			map.put("document", searchDocument);
			map.put("template", buffer.toString());
			if (form != null && form.getStyle() != null) {
				map.put("style", form.getStyle());
			}
			return success("ok", map);
		} finally {
			context.reset();
		}
	}

	/**
	 * 查询树形视图
	 * @param applicationId 软件id
	 * @param id 视图id
	 * @param keyword 关键字
	 * @return
	 * @throws Exception
	 */
	@GetMapping(path = "/views/{id}/tree/search")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "查询树形视图", notes = "查询树形视图")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "keyword",value = "关键字",required = false,paramType = "query",dataType = "string")
	})
	public Resource viewTreeSearch(@PathVariable String applicationId, @PathVariable String id, @RequestParam(required=false) String keyword) throws Exception{
		IUser user = getUser();
		ParamsTable params = getParams();
		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(id);
		if(view==null) {
			String error = String.format("viewTreeSearch找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}

		Document sDoc;
		if (view.getSearchForm() != null) {
			sDoc = view.getSearchForm().createDocument(getParams(), getUser());
		} else {
			sDoc = new Document();
		}
		params.setParameter("application", applicationId);
		params.setParameter("_viewid", id);
		params.setParameter("bname", keyword);
		DocumentTree tree = new DocumentTree(view, params, user, sDoc);
		tree.search();
		return success("ok", JSONArray.parseArray(tree.toSearchJSON()));
	}

	/**
	 * 视图列的提交按钮
	 * @param applicationId
	 * 			软件id
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/views/{viewId}/column/submit")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "视图列的提交按钮", notes = "视图列的提交按钮")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "viewId",value = "视图id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "json",value = "请求包体",required = true,paramType = "body",dataType = "string")
	})
	public Resource viewColumnApprove(@PathVariable String applicationId, @PathVariable String viewId, @RequestBody String json) throws Exception {
		JSONObject jsonObject = JSONObject.parseObject(json);
		String docId = jsonObject.getString("docId");
		String limistStrList = jsonObject.getString("approveLimit");
		String attitude = jsonObject.getString("attitude");

		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(applicationId);
			Collection<String> limistList = new ArrayList<String>();
			if (!StringUtil.isBlank(limistStrList)) {
				limistList = Arrays.asList(limistStrList.split(","));
			}

			ParamsTable params = getParams();
			params.setParameter("_attitude", attitude);
			params.setParameter("_viewid", viewId);

			DocumentProcess docProcess = RunTimeServiceManager.documentProcess(applicationId);
			net.sf.json.JSONObject jsonOb = docProcess.doBatchApprove(new String[]{docId}, getUser(), Environment.getInstance(), params, limistList);
			String result = jsonOb.getString("content");
			return success("ok", result);
		} finally {
			context.reset();
		}
	}
	/**
	 * 判断视图打开权限
	 * @param applicationId 软件id
	 * @param formid 表单id
	 * @param docid 文档id
	 * @return
	 * @throws Exception
	 */
	@GetMapping(path = "/views/{viewId}/openable")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "判断视图打开权限", notes = "判断视图打开权限")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "viewId",value = "视图id",required = true,paramType = "path",dataType = "string")
	})
	public Resource viewsOpenable(@PathVariable String applicationId, @PathVariable String viewId) throws Exception {
		ViewDesignTimeService viewService = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = (AbstractView) viewService.doView(viewId);
		if(view==null) {
			String error = String.format("找不到(app=%s)视图:%s", applicationId, viewId);
			throw new SaasNofoundException(error);
		}

		boolean allow = true;
		if(!ViewConstant.PERMISSION_TYPE_PUBLIC.equals(view.getPermissionType())){
			IUser user = getUser();
			String[] roleids = user.getRolelist(applicationId).split(",");
			allow = PermissionUtil.check(roleids, viewId, viewId, OperationVO.FORM_VIEW_ALLOW_OPEN);
		}
		return success("ok", allow);
	}

	/**
	 * 刷新表单
	 * @param applicationId 软件id
	 * @param formid 表单id
	 * @param docid 文档id
	 * @param content
	 * @return
	 * @throws Exception
	 */
	@PostMapping(path = "/views/{viewid}/documents/{docid}/refresh")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "刷新一行数据", notes = "刷新一行数据")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "viewid",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "docid",value = "文档Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "content",value = "请求内容",required = true,paramType = "body",dataType = "string")
	})
	public Resource rowRefresh(@PathVariable String applicationId, @PathVariable String viewid,
							   @PathVariable String docid, @RequestBody String content) throws Exception {
		IUser user = getUser();
		if (user == null) {
			throw new Exception("用户未登陆");
		}

		// 从Session中获取Document
		Document doc = (Document) MemoryCacheUtil.getFromPrivateSpace(docid, user);

		JSONArray items = new JSONArray();

		doc = doc==null ? new Document(): doc;

//		ParamsTable params = getParams();
		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(viewid);
		if(view==null) {
			String error = String.format("rowRefresh找不到(app=%s)视图:%s", applicationId, viewid);
			throw new SaasNofoundException(error);
		}

		IRunner runner = JavaScriptFactory.getInstance(
				user.getSessionid(), view.getApplicationid());
		runner.initBSFManager(doc, getParams(), getUser(), new ArrayList<ValidateMessage>());
		for (Iterator<Column> iterator = view.getColumns().iterator(); iterator.hasNext();) {
			Column column = iterator.next();
			if ("COLUMN_TYPE_SCRIPT".equals(column.getType())){//计算类型
				String script = column.getValueScript();
				Object result = runner.run(column,"rowRefresh.View["+view.getName()+"].Column["+ column.getName() +"]", script);

				JSONObject item = new JSONObject();
				item.put("columnid", column.getId());
				item.put("value", result);
				items.add(item);
			}
		}
		Map<String, Object> refresh = new HashMap<String, Object>();

		refresh.put("docid", docid);
		refresh.put("viewid", viewid);
		refresh.put("items", items);
		return success("ok", refresh);
	}

	/**
	 * 获取视图列筛选数据
	 * @param applicationId 软件id
	 * @param viewId 视图id
	 * @param fieldName 字段名称
	 * @return
	 * @throws Exception
	 */
	@PostMapping(path = "/views/{id}/filterColumns")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取视图列筛选数据", notes = "获取视图列筛选数据")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "applicationId",value = "软件id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "id",value = "视图Id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "parentId",value = "父Id",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "isRelate",value = "是否父子关系",required = false,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "fieldName",value = "筛选字段名称",required = true,paramType = "query",dataType = "string"),
			@ApiImplicitParam(name = "content",value = "请求包体",required = false,paramType = "body",dataType = "string"),
	})
	public Resource filterColumns(@PathVariable String applicationId, @PathVariable String id, @RequestParam(required = false) String parentId, String fieldName, @RequestParam(required = false) String isRelate, @RequestBody String content) throws Exception {
		ViewDesignTimeService vProcess = DesignTimeServiceManager.viewDesignTimeService();
		AbstractView view = vProcess.doView(id);
		if(view==null) {
			String error = String.format("filterColumns找不到(app=%s)视图:%s", applicationId, id);
			throw new SaasNofoundException(error);
		}

		TenantContext context = TenantContext.getInstance();
		try {
			context.setCurrentApplicationId(applicationId);
			ParamsTable params = getParams(); // 获取并设置参数
			IUser user = getUser();
			Document searchDocument = null;
			DataPackage<Document> dataPackage = null;
			Collection<Document> data = null;

			if (!StringUtil.isBlank(content)) {
				JSONObject jsonObject = JSONObject.parseObject(content);
				for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					params.setParameter(key, value);
				}
			}
			if (view.getSearchForm() != null) {
				Form searchForm = view.getSearchForm();
				searchDocument = searchForm.createDocument(params, user);

				IRunner runner = JavaScriptFactory.getInstance(session.getId(), view.getApplicationid());
				runner.initBSFManager(searchDocument, params, user, new ArrayList<ValidateMessage>());
				for (Map.Entry<String, Object> entry : searchDocument.getItemMap().entrySet()) {
					String key = entry.getKey();
					Object value = entry.getValue();
					if (value instanceof Date) {
						FormField filed = searchForm.findFieldByName(key);
						//此处会把params里面有的字段且为时间格式的话，会转成国际标准，需要格式化
						if (filed != null && filed instanceof DateField) {

							value = DateUtil.format((Date) value, ((DateField) filed).getDatePatternValue());
						} else {
							value = DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss");
						}
					} else {
						FormField filed = searchForm.findFieldByName(key);
						//处理下拉框没有默认值问题
						if ((value == null || value.equals("")) && filed != null && filed instanceof SelectField) {
							((SelectField) filed).getOptions(runner, searchDocument, user);
							value = searchDocument.getItemValueAsString(key);
						}
					}
					if (value != null) {
						params.setParameter(key, value);
					}
				}
			} else {
				searchDocument = new Document();
			}
			if ("true".equals(isRelate)) {
				params.setParameter("parentid", parentId);
				params.setParameter("relateid", parentId);
			} else {
				params.removeParameter("parentId");
				params.removeParameter("parentid");
				params.setParameter("relateid", parentId);
			}
			params.setParameter("lines", Integer.MAX_VALUE);

			List<Object> result = view.getViewTypeImpl().getFilterColumnDatas(fieldName, params, user, searchDocument);
			result.sort(new Comparator<Object>() {
				@Override
				public int compare(Object o1, Object o2) {
					return 1;
				}
			});
			return success("ok", result);
		}
		finally {
			context.reset();
		}
	}

	public String getPropertyByMultiLanguage(HttpServletRequest request, String applicationId, String multiLanguageLabel, String name){

		String language = MultiLanguageProperty.getLanguageByRequestLocal(request);
		String text = "";
		try {
			text = MultiLanguageProperty.getProperty(applicationId,language , multiLanguageLabel,name);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return text;
	}

	/**
	 * 获取按钮的标签名称
	 * @param formName
	 * @param activity
	 * @param runner
	 * @return
	 */
	private String getActivityLabel(String viewName, Activity activity, IRunner runner) throws Exception{
		String labelScript = activity.getLabel();
		if(!StringUtil.isBlank(labelScript)){
			StringBuffer label = new StringBuffer();
			label.append("ViewName:").append(viewName);
			label.append(" Activity(").append(activity.getId()).append(")." + activity.getName()).append(".labelScript");
			Object result = runner.run(activity, label.toString(), labelScript);
			if(result != null){
				return String.valueOf(result);
			}
		}
		return "";
	}
}
