// 声明该类所在的包，此包为资源控制器相关的包
package com.xmomen.module.resource.controller;

// 导入自定义框架中的业务异常类，用于处理业务逻辑中出现的异常
import com.xmomen.framework.exception.BusinessException;
// 导入自定义框架中 MyBatis 分页相关的 Page 类，用于处理分页查询结果
import com.xmomen.framework.mybatis.page.Page;
// 导入自定义模块中的日志注解，用于记录操作日志
import com.xmomen.module.logger.Log;
// 导入资源查询模型类，用于封装资源查询的条件
import com.xmomen.module.resource.model.ResourceQuery;
// 导入资源数据模型类，用于封装资源的相关数据
import com.xmomen.module.resource.model.ResourceModel;
// 导入资源服务类，该类包含资源相关的业务逻辑
import com.xmomen.module.resource.service.ResourceService;

// 导入 Apache Commons IO 工具类，用于处理输入输出流
import org.apache.commons.io.IOUtils;
// 导入 Jeecg 框架中 Excel 导入工具类，用于从 Excel 文件中导入数据
import org.jeecgframework.poi.excel.ExcelImportUtil;
// 导入 Jeecg 框架中 Excel 导出参数类，用于配置 Excel 导出的参数
import org.jeecgframework.poi.excel.entity.ExportParams;
// 导入 Jeecg 框架中 Excel 导入参数类，用于配置 Excel 导入的参数
import org.jeecgframework.poi.excel.entity.ImportParams;
// 导入 Jeecg 框架中 Excel 导入结果类，用于封装 Excel 导入的结果
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
// 导入 Jeecg 框架中普通 Excel 常量类，包含一些 Excel 操作的常量
import org.jeecgframework.poi.excel.entity.vo.NormalExcelConstants;
// 导入 Jeecg 框架中 Excel 导入异常类，用于处理 Excel 导入过程中出现的异常
import org.jeecgframework.poi.exception.excel.ExcelImportException;
// 导入 Spring 框架中的自动装配注解，用于自动注入依赖的 Bean
import org.springframework.beans.factory.annotation.Autowired;
// 导入 Spring 框架中的模型映射类，用于在控制器和视图之间传递数据
import org.springframework.ui.ModelMap;
// 导入 Spring 框架中的数据绑定结果类，用于处理数据绑定过程中的错误信息
import org.springframework.validation.BindingResult;
// 导入 Spring 框架中的请求映射相关注解，用于处理 HTTP 请求
import org.springframework.web.bind.annotation.*;
// 导入 Spring 框架中用于处理多部分文件上传的类
import org.springframework.web.multipart.MultipartFile;
// 导入 Spring 框架中的模型和视图类，用于返回包含模型数据和视图名称的对象
import org.springframework.web.servlet.ModelAndView;

// 导入 JSR-303 验证框架中的有效注解，用于对请求参数进行验证
import javax.validation.Valid;
// 导入 Java 序列化接口，用于支持对象的序列化和反序列化
import java.io.Serializable;
// 导入 Java 输入输出异常类，用于处理输入输出操作中出现的异常
import java.io.IOException;
// 导入 Java 输入流类，用于读取数据
import java.io.InputStream;
// 导入 Java 列表接口，用于存储多个元素
import java.util.List;

/**
 * 资源控制器类，负责处理与资源目录相关的 HTTP 请求。
 *
 * @author tanxinzheng
 * @version 1.0.0
 * @date 2017-4-10 23:26:20
 */
// 标记该类为 RESTful 风格的控制器，会自动将方法返回值转换为 JSON 格式
@RestController
// 定义该控制器处理的请求路径前缀为 /resource
@RequestMapping(value = "/resource")
public class ResourceController {

    // 使用自动装配注解将 ResourceService 注入到当前类中，用于调用资源相关的业务逻辑
    @Autowired
    ResourceService resourceService;

    /**
     * 处理获取资源目录列表的请求。
     *
     * @param limit 每页显示的结果数量
     * @param offset 当前页码
     * @param id 资源的主键，可选参数
     * @param entityType 资源所属的实体类型，可选参数
     * @param entityId 资源所属的实体 ID，可选参数
     * @param ids 资源主键数组，可选参数
     * @param excludeIds 不包含的资源主键数组，可选参数
     * @return 包含资源目录数据的分页对象
     */
    // 映射 HTTP GET 请求到该方法
    @RequestMapping(method = RequestMethod.GET)
    // 使用日志注解记录该操作的名称为查询资源目录列表
    @Log(actionName = "查询资源目录列表")
    public Page<ResourceModel> getResourceList(
            // 从请求参数中获取每页结果数
            @RequestParam(value = "limit") Integer limit,
            // 从请求参数中获取页码
            @RequestParam(value = "offset") Integer offset,
            // 从请求参数中获取资源主键，该参数可选
            @RequestParam(value = "id", required = false) String id,
            // 从请求参数中获取资源所属的实体类型，该参数可选
            @RequestParam(value = "entityType", required = false) String entityType,
            // 从请求参数中获取资源所属的实体 ID，该参数可选
            @RequestParam(value = "entityId", required = false) String entityId,
            // 从请求参数中获取资源主键数组，该参数可选
            @RequestParam(value = "ids", required = false) String[] ids,
            // 从请求参数中获取不包含的资源主键数组，该参数可选
            @RequestParam(value = "excludeIds", required = false) String[] excludeIds) {
        // 创建资源查询对象
        ResourceQuery resourceQuery = new ResourceQuery();
        // 设置查询条件：资源主键
        resourceQuery.setId(id);
        // 设置查询条件：不包含的资源主键数组
        resourceQuery.setExcludeIds(excludeIds);
        // 设置查询条件：资源主键数组
        resourceQuery.setIds(ids);
        // 设置查询条件：资源所属的实体类型
        resourceQuery.setEntityType(entityType);
        // 设置查询条件：资源所属的实体 ID
        resourceQuery.setEntityId(entityId);
        // 调用资源服务的方法，根据分页信息和查询条件获取资源目录分页数据
        return resourceService.getResourceModelPage(limit, offset, resourceQuery);
    }

    /**
     * 处理获取单个资源目录的请求。
     *
     * @param id 资源的主键
     * @return 资源目录的数据模型对象
     */
    // 映射形如 /resource/{id} 的 HTTP GET 请求到该方法
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    // 使用日志注解记录该操作的名称为查询资源目录
    @Log(actionName = "查询资源目录")
    public ResourceModel getResourceById(
            // 从路径中获取资源主键
            @PathVariable(value = "id") String id) {
        // 调用资源服务的方法，根据主键获取单个资源目录的数据
        return resourceService.getOneResourceModel(id);
    }

    /**
     * 处理新增资源目录的请求。
     *
     * @param resourceModel 包含新增资源目录信息的数据模型对象
     * @return 新增后的资源目录的数据模型对象
     */
    // 映射 HTTP POST 请求到该方法
    @RequestMapping(method = RequestMethod.POST)
    // 使用日志注解记录该操作的名称为新增资源目录
    @Log(actionName = "新增资源目录")
    public ResourceModel createResource(
            // 从请求体中获取新增资源目录的数据，并进行数据验证
            @RequestBody @Valid ResourceModel resourceModel) {
        // 调用资源服务的方法，创建新的资源目录
        return resourceService.createResource(resourceModel);
    }

    /**
     * 处理更新资源目录的请求。
     *
     * @param id 要更新的资源的主键
     * @param resourceModel 包含更新后资源目录信息的数据模型对象
     */
    // 映射形如 /resource/{id} 的 HTTP PUT 请求到该方法
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    // 使用日志注解记录该操作的名称为更新资源目录
    @Log(actionName = "更新资源目录")
    public void updateResource(
            // 从路径中获取要更新的资源主键
            @PathVariable(value = "id") String id,
            // 从请求体中获取更新后的资源目录数据，并进行数据验证
            @RequestBody @Valid ResourceModel resourceModel) {
        // 调用资源服务的方法，更新资源目录信息
        resourceService.updateResource(resourceModel);
    }

    /**
     * 处理删除单个资源目录的请求。
     *
     * @param id 要删除的资源的主键
     */
    // 映射形如 /resource/{id} 的 HTTP DELETE 请求到该方法
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    // 使用日志注解记录该操作的名称为删除单个资源目录
    @Log(actionName = "删除单个资源目录")
    public void deleteResource(
            // 从路径中获取要删除的资源主键
            @PathVariable(value = "id") String id) {
        // 调用资源服务的方法，删除指定主键的资源目录
        resourceService.deleteResource(id);
    }

    /**
     * 处理批量删除资源目录的请求。
     *
     * @param ids 要删除的资源的主键数组
     */
    // 映射 HTTP DELETE 请求到该方法
    @RequestMapping(method = RequestMethod.DELETE)
    // 使用日志注解记录该操作的名称为批量删除资源目录
    @Log(actionName = "批量删除资源目录")
    public void deleteResources(
            // 从请求参数中获取要删除的资源主键数组
            @RequestParam(value = "ids") String[] ids) {
        // 调用资源服务的方法，批量删除指定主键的资源目录
        resourceService.deleteResource(ids);
    }
}