package cn.com.qmth.stmms.file.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import cn.com.qmth.stmms.common.upyun.UpYun;

/**
 * 模拟又拍云的数据接口，提供局域网内的文件上传/下载服务
 * 
 * @author luoshi
 * 
 */
@Controller("fileApiController")
@RequestMapping("/file")
public class FileController implements InitializingBean {

    protected static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Value("${file.root}")
    private String baseDir;

    private boolean enable;

    @RequestMapping(value = "/**", method = { RequestMethod.PUT, RequestMethod.POST })
    public void upload(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (enable == false) {
            response.sendError(500, "file api disable");
            return;
        }

        File full = new File(baseDir, getFilePath(request));
        File parent = full.getParentFile();
        if (parent.exists() || parent.mkdirs()) {
            try {
                OutputStream output = new FileOutputStream(full);
                IOUtils.copy(request.getInputStream(), output);
                output.close();

                String md5 = request.getHeader(UpYun.CONTENT_MD5);
                if (StringUtils.isNotBlank(md5)) {
                    // 文件内容MD5摘要验证
                    if (!UpYun.md5(full).equals(md5)) {
                        logger.error("md5 check faile: " + full.getAbsolutePath());
                        response.sendError(500, "md5 check faile: " + full.getAbsolutePath());
                    }
                }
            } catch (Exception e) {
                logger.error("write file faile: " + full.getAbsolutePath(), e);
                response.sendError(500, "write file faile: " + full.getAbsolutePath());
            }
        } else {
            logger.error("mkdir faile: " + parent.getAbsolutePath());
            response.sendError(500, "mkdir faile: " + parent.getAbsolutePath());
        }
    }

    @RequestMapping(value = "/**", method = RequestMethod.GET)
    public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (enable == false) {
            response.sendError(500, "file api disable");
            return;
        }

        String filePath = getFilePath(request);
        File full = new File(baseDir, filePath);
        if (full.exists()) {
            try {
                IOUtils.copy(new FileInputStream(full), response.getOutputStream());
            } catch (Exception e) {
                logger.error("read file faile: " + full.getAbsolutePath(), e);
                response.sendError(500, "read file faile: " + full.getAbsolutePath());
            }
        } else {
            logger.error("file not found: " + filePath);
            response.sendError(404, "file not found: " + filePath);
        }
    }

    @RequestMapping(value = "/**", method = RequestMethod.HEAD)
    public void info(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (enable == false) {
            response.sendError(500, "file api disable");
            return;
        }

        String filePath = getFilePath(request);
        File full = new File(baseDir, filePath);
        if (full.exists()) {
            try {
                response.addHeader(UpYun.X_UPYUN_FILE_TYPE, full.isFile() ? "file" : "folder");
                response.addHeader(UpYun.X_UPYUN_FILE_SIZE, String.valueOf(full.length()));
                response.addHeader(UpYun.X_UPYUN_FILE_DATE, String.valueOf(full.lastModified()));
                if (full.isFile()) {
                    response.addHeader(UpYun.CONTENT_MD5, UpYun.md5(full));
                }
            } catch (Exception e) {
                logger.error("read file faile: " + full.getAbsolutePath(), e);
                response.sendError(500, "read file faile: " + full.getAbsolutePath());
            }
        } else {
            logger.error("file not found: " + filePath);
            response.sendError(404, "file not found: " + filePath);
        }
    }

    private String getFilePath(HttpServletRequest request) {
        return request.getRequestURI().substring(5);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (StringUtils.isNotBlank(baseDir)) {
            File dir = new File(baseDir);
            if (dir.exists() && dir.isDirectory()) {
                enable = true;
            }
        }
    }
}
