package cn.com.ty.lift.ud.fileUpload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
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.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.uniteidea.fileserver.upload.FileUploadFactory;
import com.uniteidea.fileserver.upload.FileUploadHelper;
import com.uniteidea.fileserver.upload.FileVo;
import com.uniteidea.fileserver.upload.JsonFileVo;

import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.ty.lift.common.verify.Validate;
import cn.com.ty.lift.ud.config.OssConfigutatioin;
import cn.com.ty.lift.ud.utils.ImgUtils;
import cn.com.ty.lift.ud.utils.WaterMarkUtils;
import cn.com.xwy.boot.web.dto.RestResponse;
import io.swagger.annotations.Api;

/**
 * 文件相关api. files
 *
 * @since 2017年2月17日
 */
@Controller
//@CrossOrigin
@Api(tags = "文件上传 API")
@RequestMapping("/files")
public class FilesController {

    private static final Logger LOG = LoggerFactory.getLogger(FilesController.class);
    @Autowired
    private OssConfigutatioin ossConfigutatioin;

    /**
     * 阿里oss文件上传
     *
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "oss", method = RequestMethod.POST)
    public RestResponse uploadFileByOss(MultipartHttpServletRequest request, HttpServletResponse response) {
        FIleJsonFileVo rtn = new FIleJsonFileVo(false, "上传失败");
        Iterator<String> fileNames = request.getFileNames();

        List<MultipartFile> files;
        String dir = "upload/" + FileUploadHelper.getSubTimeFolder();
        while (fileNames.hasNext() && (files = request.getFiles(fileNames.next())).size() > 0) {
            for (MultipartFile file : files) {
                String newName = FileUploadHelper.getUUID();
                String suffix = "." + FileUploadHelper.getExtensionName(file.getOriginalFilename());
                String newFileName = newName + suffix;

                String relativeUrlFileName = dir + newFileName;

                String fullUrlFileName = null;
                try {
                    fullUrlFileName = ossConfigutatioin.build().putObject(relativeUrlFileName, file.getBytes());

                    // 获取视频第一帧图片并上传
                    fetchSavePicToOss(newName, dir, file, rtn);
                } catch (Exception e) {
                    LOG.error("upload file occur exception", e);

                    return RestResponse.fail(e.getMessage());
                }
                LOG.info("upload file complete, file URL: {}", fullUrlFileName);
                Validate.notNull(fullUrlFileName, ValuePool.UPLOAD_FAIL);

                rtn.setPathUrl(fullUrlFileName);
                rtn.setPath(relativeUrlFileName);
                rtn.setNameOrg(file.getOriginalFilename());
                rtn.setSize(file.getSize());
                rtn.setFlag(true);
                rtn.setMsg("上传成功");

                // 虽然请求支持多个文件上传，但是暂时只限制上传单个文件
                break;
            }
        }

        return RestResponse.success(rtn);
    }

    @ResponseBody
    @RequestMapping(method = RequestMethod.POST)
    public RestResponse upload(MultipartHttpServletRequest request, HttpServletResponse response) {
        LOG.debug("uploadPost called begian ====");
        JsonFileVo vo = new JsonFileVo(false, "请求非法.");
        FileVo fv = new FileVo();
        try {
            fv.setPath(request.getParameter("path"));
            Iterator<String> itr = request.getFileNames();
            MultipartFile mpf;
            while (itr.hasNext()) {
                mpf = request.getFile(itr.next());
                LOG.debug("文件上传准备 {}", mpf.getOriginalFilename());
                fv.setSize(mpf.getSize());
                // 设置后缀
                fv.setType("." + FileUploadHelper.getExtensionName(mpf.getOriginalFilename()));
                fv.setNameOrg(mpf.getOriginalFilename());
                fv.setFileInputStream(mpf.getInputStream());
                LOG.debug("文件上传meta:{}", fv);
                // 有效性检验
                if (StringUtils.isEmpty(fv.getType()) || null == fv.getFileInputStream()
                    || StringUtils.isEmpty(fv.getNameOrg())) {
                    LOG.warn("文件上传数据不足,类型或无上传文件,结束上传.");
                    continue;
                }
                FileUploadFactory.uploadFileInputStream(fv);
                if (fv.isUpload()) {
                    String pathUrl = FileUploadHelper.getInstance().getFileServerUrl() + fv.getRelativePath();
                    vo.setPathUrl(pathUrl);
                    vo.setPath(fv.getRelativePath());
                    vo.setNameOrg(fv.getNameOrg());
                    vo.setSize(fv.getSize());
                    vo.setFlag(true);
                    vo.setMsg("上传成功");

                    // 获取视频第一帧图片并上传
                    fetchSavePic(fv, vo);
                    // 图片添加水印
                    WaterMarkUtils.mark("/usr/local/files/ty/" + fv.getRelativePath(),
                        "/usr/local/files/ty/" + fv.getRelativePath(), "图片来源天域电梯");
                    LOG.debug("文件上传OK:{} -> {}", fv.getNameOrg(), fv.getRelativePath());
                } else {
                    vo.setMsg(fv.getErrorMsg());
                    LOG.error("文件上传失败:{} -> {}", fv.getNameOrg(), fv.getErrorMsg());
                }
                break;// 先只考虑一个上传的情况
            }
        } catch (Exception e) {
            LOG.error("Could not upload file ", e);
        }
        LOG.debug("uploadPost called end ====");
        return RestResponse.success(vo, "上传成功");
    }

    /**
     * 判断是否是视频类型文件
     *
     * @param ex
     * @return
     */
    private boolean isVedioFile(String ex) {
        String[] s = {"mp4", "rmvb", "mov", "wmv"};
        Set<String> typeFiles = new HashSet<>(Arrays.asList(s));
        if (typeFiles.contains(ex.toLowerCase())) {
            return true;
        }

        return false;
    }

    /**
     * 判断是否是图片类型文件
     *
     * @param ex
     * @return
     */
    private boolean isPictureFile(String ex) {
        String[] s = {"jpg", "png"};
        Set<String> typeFiles = new HashSet<>(Arrays.asList(s));
        if (typeFiles.contains(ex.toLowerCase())) {
            return true;
        }

        return false;
    }

    /**
     * 截取视频第一帧文件并且上传文件
     *
     * @param fv
     * @param vo
     */
    private void fetchSavePic(FileVo fv, JsonFileVo vo) {
        if (isVedioFile(FileUploadHelper.getExtensionName(fv.getNameOrg()))) {
            // 使用毫秒数作为图片名
            String fileName = fv.getNameNew().substring(0, fv.getNameOrg().lastIndexOf(46)) + "-cover.jpg";
            try {
                // 将input转换成file
                /*InputStream ins = fv.getFileInputStream();
                File f = new File(fv.getNameOrg());
                ImgUtils.inputStreamToFile(ins, f);*/

                // 获取视频第一帧图片字节码
                String videoLocation = FileUploadHelper.getInstance().getUploadLocalPath() + fv.getRelativePath();
                File videoFile = new File(videoLocation);
                String imgFileString = ImgUtils.fetchPic(videoFile);
                if (imgFileString.indexOf("base64,") >= 0) {
                    imgFileString = imgFileString.split("base64,")[1];
                }
                byte[] b = Base64.decodeBase64(imgFileString);
                for (int i = 0; i < b.length; ++i) {
                    if (b[i] < 0) { // 调整异常数据
                        b[i] += 256;
                    }
                }

                // 将图片写入输出到指定位置
                File tempFile = new File(FileUploadHelper.getInstance().getUploadLocalPath() + fv.getPath() + fileName);
                OutputStream out = new FileOutputStream(tempFile);
                out.write(b);
                out.flush();
                out.close();

                vo.setNameNew(fv.getPath() + fileName);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * @param newFileName
     *            上传文件新名称
     * @param dir
     *            上传文件目录
     * @param multipartFile
     *            上传的源文件
     * @param vo
     *            返回参数
     */
    private void fetchSavePicToOss(String newFileName, String dir, MultipartFile multipartFile, FIleJsonFileVo vo)
        throws Exception {
        if (isVedioFile(FileUploadHelper.getExtensionName(multipartFile.getOriginalFilename()))) {

            String fileName = newFileName + "-cover.jpg";

            // 获取视频第一帧图片字节码
            String imgFileString = ImgUtils.fetchPic(multipartFile.getInputStream());
            if (imgFileString.indexOf("base64,") >= 0) {
                imgFileString = imgFileString.split("base64,")[1];
            }
            byte[] b = Base64.decodeBase64(imgFileString);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) { // 调整异常数据
                    b[i] += 256;
                }
            }
            String relativeUrlFileName = dir + fileName;
            String fullPath = ossConfigutatioin.build().putObject(relativeUrlFileName, b);

            vo.setCoverUrl(fullPath);
            vo.setCover(relativeUrlFileName);
        }
    }
}
