package cn.myapps.runtime.chart.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.bcxin.saas.core.utils.SqlUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.alibaba.fastjson.JSONObject;

import cn.myapps.base.web.WebUser;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.model.chart.Chart;
import cn.myapps.common.model.view.AbstractView;
import cn.myapps.common.util.StringUtil;
import cn.myapps.designtime.chart.service.ChartDesignTimeService;
import cn.myapps.designtime.common.service.DesignTimeServiceManager;
import cn.myapps.designtime.form.service.FormDesignTimeService;
import cn.myapps.designtime.view.service.ViewDesignTimeService;
import cn.myapps.runtime.common.controller.AbstractRuntimeController;
import cn.myapps.runtime.dynaform.PermissionType;
import cn.myapps.runtime.dynaform.document.ejb.Document;
import cn.myapps.runtime.dynaform.document.model.IDocument;
import cn.myapps.runtime.dynaform.form.ejb.Form;
import cn.myapps.runtime.dynaform.form.ejb.FormElement;
import cn.myapps.runtime.dynaform.form.ejb.FormField;
import cn.myapps.runtime.dynaform.form.ejb.ValidateMessage;
import cn.myapps.runtime.dynaform.form.ejb.ValueStoreField;
import cn.myapps.runtime.macro.runner.IRunner;
import cn.myapps.runtime.macro.runner.JavaScriptFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
 * Chart Restful 接口
 * @author spy
 */
@Api(tags = "统计图执行模块")
@Component
@RequestMapping(path = "/api/runtime", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class ChartController extends AbstractRuntimeController {

	/**
	 * 获取统计图的数据内容
	 * @param id 统计图id
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/chart/{id}")
	@ResponseStatus(HttpStatus.OK)
	@ApiOperation(value = "获取统计图的数据内容", notes = "获取统计图的数据内容")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id",value = "统计图id",required = true,paramType = "path",dataType = "string"),
			@ApiImplicitParam(name = "content",value = "请求包体",required = false,paramType = "body",dataType = "string")
	})
	public Resource doGetChartData(@PathVariable String id,@RequestBody(required = false) String content) throws Exception{

		content = SqlUtil.encode(content);
		Object result = "";
		Map data = new HashMap();
		ChartDesignTimeService chartservice =DesignTimeServiceManager.chartDesignTimeService();
		Chart chart =  (Chart)chartservice.doView(id);
		ParamsTable params = getParams(); // 获取并设置参数
		if(chart !=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);
				}
			}
			Document searchDocument;
			if (!StringUtil.isBlank(chart.getSearchFormId())) {
				FormDesignTimeService fs = DesignTimeServiceManager.formDesignTimeService();
				//图表中的查询表单id
				Form searchForm = fs.doView(chart.getSearchFormId());
				searchDocument = searchForm.createDocument(params, getUser());
			} else {
				searchDocument = new Document();
			}
			//生成EChart图表数据
			result = buildEChartOption(chart, this.getParams(), getUser(), searchDocument);
		}
		//获取点击图表跳转到的视图id
		String viewId = chart.getViewId();
		AbstractView view = null;
		if(!StringUtil.isBlank(viewId)){
			ViewDesignTimeService viewDesignTimeService = DesignTimeServiceManager.viewDesignTimeService();
			view = viewDesignTimeService.doView(viewId);
		}
		data.put("result",result);
		data.put("view",view);
		data.put("appId",chart.getApplicationid());
		return success("ok", data);
	}

	private Object buildEChartOption(Chart chart, ParamsTable params, WebUser user, IDocument doc) throws Exception {
		Object optionText = "";
		if (!StringUtil.isBlank(chart.getScripttext())) {
			IRunner runner = JavaScriptFactory.getInstance(user.getSessionid(), chart.getApplicationid());
			runner.initBSFManager(doc, params, user, new ArrayList<ValidateMessage>());
			try {
				String scriptText = chart.getScripttext();
				scriptText = "JSON.stringify("+scriptText+")";

				Object result = runner.run(chart,"Chart[" + chart.getName() + "]-" + chart.getId(), scriptText);
				optionText =  result;
                 /*if (result instanceof String) {
                 } else {
                     throw new Exception("Chart[" + chart.getName() + "]脚本运算结果不合法，请返回字符串！");
                 }*/
			} catch (Exception e) {
				e.printStackTrace();
				optionText = e.getMessage();
			}
		}
		return optionText;
	}

	/**
	 * 获取查询表单模板
	 * @param applicationId 软件id
	 * @param id 统计图id
	 * @return
	 * @throws Exception
	 */
	@GetMapping(path = "/chart/{id}/searchformtemplate/{applicationId}")
	@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{
		WebUser user = getUser();
		ParamsTable params = getParams();
		ChartDesignTimeService chartService = DesignTimeServiceManager.chartDesignTimeService();
		Chart chart = chartService.doView(id);
		IRunner runner = JavaScriptFactory.getInstance(user.getSessionid(), applicationId);
		Document searchDocument = null;
		if (!StringUtil.isBlank(chart.getSearchFormId())) {
			FormDesignTimeService fs = DesignTimeServiceManager.formDesignTimeService();
			//图表中的查询表单id
			Form searchForm = fs.doView(chart.getSearchFormId());
			searchDocument = searchForm.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);
	}
}
