package com.njcn.device.pq.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.pq.mapper.ResourceMapper;
import com.njcn.device.pq.pojo.po.ResourceData;
import com.njcn.device.pq.service.ResourceService;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.system.pojo.po.Resinformation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @version 1.0.0
 * @author: zbj
 * @date: 2023/05/25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, ResourceData> implements ResourceService {

    private final ResourceMapper resourceMapper;

    private final FileStorageUtil fileStorageUtil;

    //private final GeneralInfo generalInfo;

    @Override
    public Boolean uploadFile(MultipartFile multipartFile, MultipartFile picture, String name,Integer state, Integer type) {
        String resUrl = "";
        String picUrl = "";
        String imgName = "";
        //通过封装好的文件工具类来传入文件和文件夹名称来获取文件路径
        resUrl = fileStorageUtil.uploadMultipart(multipartFile, OssPath.RESOURCEDATA);
        //判断图片文件对象是否为空,不为空获取图片路径
        if (null != picture && !picture.isEmpty()) {
            picUrl = fileStorageUtil.uploadMultipart(picture, OssPath.RESOURCEDATA);
            imgName = picture.getOriginalFilename();
        }
        //创建对象
        ResourceData resourceData = new ResourceData();
        resourceData.setResourceName(name);
        resourceData.setResUrl(resUrl);
        resourceData.setPicUrl(picUrl);
        resourceData.setImgName(imgName);
        resourceData.setUploadTime(LocalDateTime.now());
        resourceData.setState(state);
        resourceData.setType(type);
        resourceData.setFileName(multipartFile.getOriginalFilename());
        return this.save(resourceData);
    }

    @Override
    public List<ResourceData> queryData(Integer type, Integer state, String searchValue) {
        List<ResourceData> list = null;
        if (null != type || null != state || StringUtils.isNotBlank(searchValue)) {
            LambdaQueryWrapper<ResourceData> wrapper = new LambdaQueryWrapper<>();
            if (null != type) {
                //type
                wrapper.eq(ResourceData::getType, type);
            }
            if (null != state) {
                //state
                wrapper.eq(ResourceData::getState, state);
            }
            if (StringUtils.isNotBlank(searchValue)) {
                //name
                wrapper.like(ResourceData::getResourceName, searchValue);
            }
            list = resourceMapper.selectList(wrapper);
        } else {
            list = this.list();
        }
        for (
                ResourceData resourceData : list) {
            resourceData.setResUrl(fileStorageUtil.getFileUrl(resourceData.getResUrl()));
            if (StringUtils.isNotBlank(resourceData.getPicUrl())) {
                resourceData.setPicUrl(fileStorageUtil.getFileUrl(resourceData.getPicUrl()));
            }
        }
        return list;
    }

    public static long getFileSize(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len;
        long size = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            size += len;
        }
        inputStream.close();
        return size;
    }

    @Override
    public void previewFile(String id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        ResourceData resourceData = resourceMapper.selectById(id);
        //获取文件流
        InputStream ins = fileStorageUtil.getFileStream(resourceData.getResUrl());
        if (StringUtils.isNotBlank(resourceData.getPicUrl())) {
            resourceData.setPicUrl(fileStorageUtil.getFileUrl(resourceData.getPicUrl()));
        }
        try (
                BufferedInputStream bis = new BufferedInputStream(ins);
                OutputStream out = response.getOutputStream()) {
            long p = 0L;
            long toLength = 0L;
            long contentLength = 0L;
            int rangeSwitch = 0;
            long fileLength;
            String rangBytes = "";
            fileLength = getFileSize(ins);
            // get file content
            // tell the client to allow accept-ranges
            response.reset();
            response.setHeader("Accept-Ranges", "bytes");
            // client requests a file block download start byte
            String range = request.getHeader("Range");
            if (range != null && range.trim().length() > 0 && !"null".equals(range)) {
                response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
                rangBytes = range.replaceAll("bytes=", "");
                if (rangBytes.endsWith("-")) { // bytes=270000-
                    rangeSwitch = 1;
                    p = Long.parseLong(rangBytes.substring(0, rangBytes.indexOf("-")));
                    contentLength = fileLength - p; // 客户端请求的是270000之后的字节(包括bytes下标索引为270000的字节)
                } else { // bytes=270000-320000
                    rangeSwitch = 2;
                    String temp1 = rangBytes.substring(0, rangBytes.indexOf("-"));
                    String temp2 = rangBytes.substring(rangBytes.indexOf("-") + 1, rangBytes.length());
                    p = Long.parseLong(temp1);
                    toLength = Long.parseLong(temp2);
                    contentLength = toLength - p + 1; // 客户端请求的是 270000-320000 之间的字节
                }
            } else {
                contentLength = fileLength;
            }
            // 如果设设置了Content-Length，则客户端会自动进行多线程下载。如果不希望支持多线程，则不要设置这个参数。
            // Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
            response.setHeader("Content-Length", Long.toString(contentLength));
            // 断点开始
            // 响应的格式是:
            // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
            if (rangeSwitch == 1) {
                String contentRange = new StringBuffer("bytes ").append(new Long(p).toString()).append("-")
                        .append(new Long(fileLength - 1).toString()).append("/")
                        .append(new Long(fileLength).toString()).toString();
                response.setHeader("Content-Range", contentRange);
                bis.skip(p);
            } else if (rangeSwitch == 2) {
                String contentRange = range.replace("=", " ") + "/" + new Long(fileLength).toString();
                response.setHeader("Content-Range", contentRange);
                bis.skip(p);
            } else {
                String contentRange = new StringBuffer("bytes ").append("0-").append(fileLength - 1).append("/")
                        .append(fileLength).toString();
                response.setHeader("Content-Range", contentRange);
            }
            String fileName = resourceData.getResourceName();
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            int n = 0;
            long readLength = 0;
            int bsize = 1024;
            byte[] bytes = new byte[bsize];
            if (rangeSwitch == 2) {
                // 针对 bytes=27000-39000 的请求，从27000开始写数据
                while (readLength <= contentLength - bsize) {
                    n = bis.read(bytes);
                    readLength += n;
                    out.write(bytes, 0, n);
                }
                if (readLength <= contentLength) {
                    n = bis.read(bytes, 0, (int) (contentLength - readLength));
                    out.write(bytes, 0, n);
                }
            } else {
                while ((n = bis.read(bytes)) != -1) {
                    out.write(bytes, 0, n);
                }
            }
            out.flush();

        } catch (Exception e) {
            log.error(e.getMessage());
        }
        //return resourceData;
    }

    @Override
    public Boolean updateFile(String id, MultipartFile multipartFile, MultipartFile picture, String name, Integer state, Integer type) {
        ResourceData resourceData = resourceMapper.selectById(id);
        //文件
        if (null != multipartFile && !multipartFile.isEmpty()) {
            //删除文件
            fileStorageUtil.deleteFile(resourceData.getResUrl());
            //获取路径
            String resUrl = fileStorageUtil.uploadMultipart(multipartFile, OssPath.RESOURCEDATA);
            resourceData.setResUrl(resUrl);
            resourceData.setFileName(multipartFile.getOriginalFilename());
        }
        //图片
        if (null != picture && !picture.isEmpty()) {
            if (StringUtils.isNotBlank(resourceData.getPicUrl())) {
                //删除图片
                fileStorageUtil.deleteFile(resourceData.getPicUrl());
            }
            //获取路径
            String picUrl = fileStorageUtil.uploadMultipart(picture, OssPath.RESOURCEDATA);
            resourceData.setPicUrl(picUrl);
            resourceData.setImgName(picture.getOriginalFilename());
        }
        if (StringUtils.isNotBlank(name)) {
            resourceData.setResourceName(name);
        }
        if (null != state) {
            resourceData.setState(state);
        }
        if (null != type) {
            resourceData.setType(type);
        }
        resourceData.setUpdateTime(LocalDateTime.now());
        int i = resourceMapper.updateById(resourceData);
        return i > 0;
    }

    @Override
    public Boolean deleteFile(String id) {
        ResourceData resourceData = resourceMapper.selectById(id);
        //删除文件
        fileStorageUtil.deleteFile(resourceData.getResUrl());
        //存在图片删除图片
        if (StringUtils.isNotBlank(resourceData.getPicUrl())) {
            fileStorageUtil.deleteFile(resourceData.getPicUrl());
        }
        //删除数据
        int i = resourceMapper.deleteById(id);
        return i > 0;
    }


/*
    @Override
    public void exportData() {
        String fileName = "资源列表.csv";
        //String targetDir = generalInfo.getBusinessTempPath() + File.separator + RequestUtil.getUserIndex();
        String targetDir = "C:\\Users\\User\\Desktop\\1";
        File excel = new File(targetDir, fileName);
        List<ResinformationParam> list = resourceAdministrationMapper.listAll();
        ExcelUtil.exportExcelWithTargetFile(excel, ResinformationParam.class, list);
    }
*/

}
