package cn.com.smart.form.controller;

import cn.com.smart.bean.SmartResponse;
import cn.com.smart.filter.bean.FilterParam;
import cn.com.smart.form.bean.QueryFormData;
import cn.com.smart.form.bean.entity.TForm;
import cn.com.smart.form.bean.entity.TFormInstance;
import cn.com.smart.form.bean.entity.TFormScript;
import cn.com.smart.form.helper.FormDataHelper;
import cn.com.smart.form.helper.FormHelper;
import cn.com.smart.form.helper.FormUploadFileHelper;
import cn.com.smart.form.service.*;
import cn.com.smart.web.ISmartWeb;
import cn.com.smart.web.bean.RequestPage;
import cn.com.smart.web.bean.UserInfo;
import cn.com.smart.web.helper.HttpRequestHelper;
import cn.com.smart.web.helper.WebSecurityHelper;
import cn.com.smart.web.service.OPService;
import cn.com.smart.web.tag.bean.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mixsmart.exception.NullArgumentException;
import com.mixsmart.utils.LoggerUtils;
import com.mixsmart.utils.StringUtils;
import org.snaker.engine.helper.JsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

/**
 * 表单实例 控制器类
 * @author lmq  2017年8月27日
 * @version 1.0
 * @since 1.0
 */
@Controller
@RequestMapping("/form/instance")
public class FormInstanceController extends BaseFormController {

    private static final String VIEW_DIR = BASE_FORM_VIEW_DIR+"instance/";
    @Autowired
    private OPService opServ;
    @Autowired
    private FormService formServ;
    @Autowired
    private IFormDataService formDataServ;
    @Autowired
    private FormInstanceService formInsServ;
    @Autowired
    private FormScriptService formScriptServ;
    @Autowired
    private FormMappingService formMappingServ;
    
    /**
     * 表单实例列表
     * @param request
     * @param searchFilter
     * @param page
     * @return
     */
    @RequestMapping("/list")
    public ModelAndView list(HttpServletRequest request, FilterParam searchFilter, RequestPage page) {
        ModelAndView modelView = new ModelAndView();
        SmartResponse<Object> smartResp = opServ.getDatas("get_form_instance_list", searchFilter, page.getStartNum(), page.getPageSize());
        String uri = HttpRequestHelper.getCurrentUri(request);
        refreshBtn = new RefreshBtn(uri, null, null);
        editBtn = new EditBtn("edit", "form/instance/edit", null, "修改表单数据", null);
        delBtn = new DelBtn("form/instance/delete", "您确定要删除选中的表单数据吗？", uri, null, null);
        ALink alink = new ALink("form/instance/view", null, "查看表单信息");
        alink.setParamIndex("4,5");
        alink.setParamName("formId,formDataId");
        alinks = new ArrayList<ALink>(1);
        alinks.add(alink);
        pageParam = new PageParam(uri, null, page.getPage(), page.getPageSize());
        
        ModelMap modelMap = modelView.getModelMap();
        modelMap.put("smartResp", smartResp);
        modelMap.put("refreshBtn", refreshBtn);
        modelMap.put("delBtn", delBtn);
        modelMap.put("editBtn", editBtn);
        modelMap.put("alinks", alinks);
        modelMap.put("pageParam", pageParam);
        modelView.setViewName(VIEW_DIR+"list");
        return modelView;
    }
    
    /**
     * 通过表单ID，创建表单视图
     * @param formId 表单ID
     * @param instId 表单实例ID（用于编辑数据）
     * @param sourceFormId 来源表单ID（映射表单来源）
     * @param sourceFormDataId 来源表单数据ID（映射表单数据来源）
     * @return 
     */
    @RequestMapping("/create")
    public ModelAndView create(String formId, String instId, String sourceFormId, String sourceFormDataId) {
        ModelAndView modelView = new ModelAndView();
        if(StringUtils.isEmpty(formId) && StringUtils.isEmpty(instId)) {
            throw new NullArgumentException("formId参数不能为空");
        }
        ModelMap modelMap = modelView.getModelMap();
        if(StringUtils.isEmpty(instId)) {
            SmartResponse<TForm> smartResp = formServ.find(formId);
            modelMap.put("objBean", smartResp.getData());
            modelMap.put("formDataId", FormDataHelper.createNewFormDataId());
            if(StringUtils.isNotEmpty(sourceFormId) && StringUtils.isNotEmpty(sourceFormDataId)) {
               SmartResponse<QueryFormData> formDataResp = formMappingServ.getFormDataMapping(sourceFormId, sourceFormDataId, formId);
               assignFormData(modelMap, formDataResp);
            }
        } else {
            TFormInstance formIns = formInsServ.find(instId).getData();
            formId = formIns.getFormId();
            handleView(modelView.getModelMap(), formIns.getFormId(), formIns.getFormDataId());
        }
        if(StringUtils.isNotEmpty(formId)) {
            //查询表单的js脚本
            TFormScript formScript = formScriptServ.getFormScript(formId);
            String jsCode = "";
            if (formScript != null) {
                jsCode = FormHelper.getAllFun(formScript);
            }
            modelMap.put("jsCode", jsCode);
        }
        String notAuthParam = "authToken=" + WebSecurityHelper.encrypt(ISmartWeb.UNAUTHORIZED_FLAG) + "&time=" + System.currentTimeMillis();
        modelMap.put("notAuthParam", notAuthParam);
        modelView.setViewName(VIEW_DIR+"create");
        return modelView;
    }
    
    /**
     * 提交表单
     * @param formId
     * @param formDataId
     * @param request 
     * @param response 
     */
    @RequestMapping(value="submit", method = RequestMethod.POST)
    public void submit(HttpServletRequest request, HttpServletResponse response,
                       String formId, String formDataId, String flag) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain;charset=UTF-8");
        SmartResponse<String> smartResp = new SmartResponse<String>();
        String msg = "提交表单失败";
        if("save".equals(flag)) {
            msg = "保存表单失败";
        }
        smartResp.setMsg(msg);
        ObjectMapper objMapper = new ObjectMapper();
        if(StringUtils.isNotEmpty(formId) && StringUtils.isNotEmpty(formDataId)) {
            UserInfo userInfo = getUserInfoFromSession(request);
            //处理参数
            Map<String,Object> params = getRequestParamMap(request, false);
            //处理附件
            CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
            if(multipartResolver.isMultipart(request)) {
                new FormUploadFileHelper((MultipartHttpServletRequest) request, params, formId, FormDataHelper.handleFormDataId(formDataId), userInfo.getId()).upload();
            }
            //TODO 保存表单数据
            smartResp = formInsServ.create(params, formDataId, formId, userInfo);
            if("save".equals(flag)) {
                if(OP_SUCCESS.equals(smartResp.getResult())) {
                    smartResp.setMsg("保存成功");
                } else {
                    smartResp.setMsg("保存失败");
                }
            }
        } 
        try {
            response.getWriter().print(objMapper.writeValueAsString(smartResp));
        } catch (IOException e) {
            e.printStackTrace();
            LoggerUtils.error(log, e.getMessage());
        }
    }
    
    /**
     * 删除表单实例
     * @param id 实例ID
     * @return 返回删除结果（JSON格式）
     */
    @RequestMapping(value="/delete", produces="application/json;charset=UTF-8")
    @ResponseBody
    public SmartResponse<String> delete(String id) {
        return formInsServ.delete(id);
    }
    
    /**
     * 修改表单数据
     * @param id 表单实例ID
     * @return
     */
    @RequestMapping("/edit")
    public ModelAndView edit(String id) {
        ModelAndView modelView = new ModelAndView();
        if(StringUtils.isNotEmpty(id)) {
            TFormInstance formIns = formInsServ.find(id).getData();
            if(null == formIns) {
                formIns = formInsServ.getFormInstByFormDataId(id).getData();
            }
            handleView(modelView.getModelMap(), formIns.getFormId(), formIns.getFormDataId());
        }
        String notAuthParam = "authToken=" + WebSecurityHelper.encrypt(ISmartWeb.UNAUTHORIZED_FLAG) + "&time=" + System.currentTimeMillis();
        modelView.getModelMap().put("notAuthParam", notAuthParam);
        modelView.setViewName(VIEW_DIR+"edit");
        return modelView;
    }
    
    /**
     * 查看表单实例
     * @param formId 表单ID
     * @param formDataId 表单数据ID
     * @return 
     */
    @RequestMapping("/view")
    public ModelAndView view(String formId, String formDataId) {
        ModelAndView modelView = new ModelAndView();
        handleView(modelView.getModelMap(), formId, formDataId);
        modelView.setViewName(VIEW_DIR+"view");
        return modelView;
    }
    
    /**
     * 处理试图
     * @param modelMap
     * @param formId
     * @param formDataId
     */
    private void handleView(ModelMap modelMap, String formId, String formDataId) {
        if(StringUtils.isNotEmpty(formId) && StringUtils.isNotEmpty(formDataId)) {
            TForm form = formServ.find(formId).getData();
            modelMap.put("objBean", form);
            modelMap.put("formId", formId);
            modelMap.put("formDataId", formDataId);
            SmartResponse<QueryFormData> smartResp = formDataServ.getFormDataByFormDataId(formDataId, formId);
            assignFormData(modelMap, smartResp);
        }
    }

    /**
     * 赋值表单数据
     * @param modelMap
     * @param smartResp
     */
    private void assignFormData(ModelMap modelMap, SmartResponse<QueryFormData> smartResp) {
        if(null == smartResp) {
            return;
        }
        String output = JsonHelper.toJson(smartResp);
        output = StringUtils.repaceSpecialChar(output);
        output = StringUtils.repaceSlash(output);
        modelMap.put("output", output);
    }
}
