package com.ibeetl.admin.console.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.ibeetl.admin.console.service.FunctionConsoleService;
import com.ibeetl.admin.console.web.query.FunctionQuery;
import com.ibeetl.admin.core.annotation.Function;
import com.ibeetl.admin.core.annotation.Query;
import com.ibeetl.admin.core.entity.CoreFunction;
import com.ibeetl.admin.core.rbac.tree.FunctionItem;
import com.ibeetl.admin.core.service.CorePlatformService;
import com.ibeetl.admin.core.util.AnnotationUtil;
import com.ibeetl.admin.core.util.ConvertUtil;
import com.ibeetl.admin.core.util.FormFieldException;
import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.util.ValidateConfig;
import com.ibeetl.admin.core.web.JsonResult;
import com.ibeetl.admin.core.web.dto.FunctionNodeView;

/**
 * 描述: 功能点管理
 *
 * @author : lijiazhi
 */
@Controller
public class FunctionController {

  private final Log log = LogFactory.getLog(this.getClass());

  private static final String MODEL = "/admin/function";
  @Autowired CorePlatformService platformService;
  @Autowired private FunctionConsoleService functionConsoleService;

  /*页面*/

  @GetMapping(MODEL + "/index.do")
  @Function("function")
  public ModelAndView index() {
    ModelAndView view = new ModelAndView("/admin/function/index.html");
    view.addObject("search", FunctionQuery.class.getName());
    return view;
  }

  @GetMapping(MODEL + "/add.do")
  @Function("function.add")
  public ModelAndView add() {
    ModelAndView view = new ModelAndView("/admin/function/add.html");
    return view;
  }

  @GetMapping(MODEL + "/edit.do")
  @Function("function.edit")
  public ModelAndView edit(Integer id) {
    ModelAndView view = new ModelAndView("/admin/function/edit.html");
    CoreFunction function = functionConsoleService.queryById(id);
    view.addObject("function", function);
    return view;
  }

  /*Json*/

  @RequestMapping(MODEL + "/add.json")
  @Function("function.add")
  @ResponseBody
  public JsonResult<CoreFunction> addFunction(
      @Validated(ValidateConfig.ADD.class) CoreFunction function) {
    String code = function.getCode();
    CoreFunction dbFunction = functionConsoleService.getFunction(code);
    if (dbFunction != null) {
      throw new FormFieldException(CoreFunction.class.getName(), "code", "已经存在");
    }

    if (function.getParentId() == null) {
      function.setParentId(0l);
    }
    function.setCreateTime(new Date());
    functionConsoleService.saveFunction(function);
    return JsonResult.success(function);
  }

  @RequestMapping(MODEL + "/update.json")
  @Function("function.update")
  @ResponseBody
  public JsonResult<?> updateFunction(
      @Validated(ValidateConfig.UPDATE.class) CoreFunction function) {
    CoreFunction dbFunction = functionConsoleService.getFunction(function.getCode());
    if (dbFunction != null && !dbFunction.getId().equals(function.getId())) {
      throw new FormFieldException(CoreFunction.class.getName(), "code", "已经存在");
    }

    if (function.getParentId() == null) {
      function.setParentId(0l);
    }
    //		function.setCreateTime(dbFunction.getCreateTime());
    functionConsoleService.updateFunction(function);
    return JsonResult.success();
  }

  @RequestMapping(MODEL + "/view.json")
  @Function("function.query")
  @ResponseBody
  public JsonResult<CoreFunction> getFunction(Long id) {
    CoreFunction function = functionConsoleService.getFunction(id);

    if (function.hasParent()) {
      CoreFunction parent = functionConsoleService.getFunction(function.getParentId());
      function.set("parentName", parent.getName());
    } else {
      function.set("parentName", "");
    }
    functionConsoleService.queryEntityAfter(function);
    return JsonResult.success(function);
  }

  @RequestMapping(MODEL + "/delete.json")
  @Function("function.delete")
  @ResponseBody
  public JsonResult deleteFunction(Long id) {
    CoreFunction fun = functionConsoleService.queryById(id);
    if (fun == null) {
      throw new PlatformException("删除失败,没有找到Function " + id + "!");
    }
    // 删除功能和所有子功能
    functionConsoleService.deleteFunction(id);
    return JsonResult.success();
  }

  /**
   * 字典列表 分页
   *
   * @param condtion
   * @return
   */
  @RequestMapping(MODEL + "/list.json")
  @Function("function.query")
  @ResponseBody
  public JsonResult<PageQuery<CoreFunction>> list(FunctionQuery condtion) {

    PageQuery page = condtion.getPageQuery();
    functionConsoleService.queryByCondtion(page);
    return JsonResult.success(page);
  }

  @PostMapping(MODEL + "/list/condition.json")
  @Function("function.query")
  @ResponseBody
  public JsonResult<List<Map<String, Object>>> listCondtion() {
    List<Map<String, Object>> list =
        AnnotationUtil.getInstance().getAnnotations(Query.class, FunctionQuery.class);
    return JsonResult.success(list);
  }

  private List<Long> findChildFunctionIds(Long funtionId) {

    FunctionItem funItem = platformService.buildFunction().findChild(funtionId);
    List<Long> children = funItem.findAllChildrenId();
    children.add(funtionId);
    return children;
  }

  @RequestMapping(MODEL + "/batchDel.json")
  @Function("function.delete")
  @ResponseBody
  public JsonResult batchDel(String ids) {
    List<Long> dels = ConvertUtil.str2longs(ids);
    functionConsoleService.batchDeleteFunction(dels);
    return new JsonResult().success();
  }

  @PostMapping(MODEL + "/tree.json")
  @Function("function.query")
  @ResponseBody
  public JsonResult<List<FunctionNodeView>> tree() {
    FunctionItem root = this.platformService.buildFunction();
    List<FunctionNodeView> tree = buildFunctionTree(root);
    return JsonResult.success(tree);
  }

  private List<FunctionNodeView> buildFunctionTree(FunctionItem node) {
    List<FunctionItem> list = node.getChildren();
    if (list.size() == 0) {
      return Collections.EMPTY_LIST;
    }
    List<FunctionNodeView> views = new ArrayList<FunctionNodeView>(list.size());
    for (FunctionItem item : list) {
      FunctionNodeView view = new FunctionNodeView();
      view.setCode(item.getData().getCode());
      view.setName(item.getData().getName());
      view.setId(item.getData().getId());
      view.setAccessUrl(item.getData().getAccessUrl());
      List<FunctionNodeView> children = this.buildFunctionTree(item);
      view.setChildren(children);
      views.add(view);
    }
    return views;
  }
}
