/**
 * Copyright (c) 2015-2020, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jboot.web.attachment;

import com.jfinal.ext.kit.DateKit;
import com.jfinal.kit.LogKit;
import com.jfinal.render.FileRender;
import io.jboot.utils.FileUtil;
import io.jboot.utils.StrUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * @author michael yang (fuhai999@gmail.com)
 */
public class LocalAttachmentContainer implements AttachmentContainer {

    private String rootPath;
    private String targetPrefix;

    public LocalAttachmentContainer() {
        LocalAttachmentContainerConfig config = LocalAttachmentContainerConfig.getInstance();
        this.rootPath = config.getRootPath();
        this.targetPrefix = config.getTargetPrefix();
    }

    /**
     * @param rootPath
     * @param targetPrefix 不能以 / 开头
     */
    public LocalAttachmentContainer(String rootPath, String targetPrefix) {
        this.rootPath = rootPath;
        this.targetPrefix = targetPrefix;
    }

    @Override
    public String saveFile(File file) {
        File newfile = newRandomFile(FileUtil.getSuffix(file.getName()));

        if (!newfile.getParentFile().exists()) {
            newfile.getParentFile().mkdirs();
        }

        try {
            org.apache.commons.io.FileUtils.moveFile(file, newfile);
            newfile.setReadable(true, false);
        } catch (IOException e) {
            LogKit.error(e.toString(), e);
        }

        String attachmentRoot = getRootPath();
        return FileUtil.removePrefix(newfile.getAbsolutePath(), attachmentRoot);
    }


    @Override
    public boolean deleteFile(String relativePath) {
        return getFile(relativePath).delete();
    }


    public File newRandomFile(String suffix) {
        String rootPath = getRootPath();

        StringBuilder newFileName = new StringBuilder(rootPath)
                .append(File.separator).append(targetPrefix)
                .append(File.separator).append(DateKit.toStr(new Date(), "yyyyMMdd"))
                .append(File.separator).append(StrUtil.uuid())
                .append(suffix);

        return new File(newFileName.toString());
    }


    @Override
    public File getFile(String relativePath) {
        return new File(getRootPath(), relativePath);
    }


    @Override
    public String getRelativePath(File file) {
        String rootPath = getRootPath();
        String filePath = file.getAbsolutePath();
        return filePath.startsWith(rootPath)
                ? filePath.substring(rootPath.length())
                : filePath;
    }


    @Override
    public boolean isRemoteContainer() {
        return false;
    }


    @Override
    public boolean matchFile(String target, HttpServletRequest request) {
        return target.startsWith(buildMatchTarget()) && target.lastIndexOf('.') != -1;
    }

    private String matchTarget = null;

    private String buildMatchTarget() {
        if (matchTarget == null) {
            synchronized (this) {
                if (matchTarget == null) {
                    matchTarget = "/" + getTargetPrefix() + "/";
                }
            }
        }
        return matchTarget;
    }


    private Boolean runInFatjar;

    protected boolean isRunInFatjar() {
        if (runInFatjar == null) {
            runInFatjar = LocalAttachmentContainer.class.getResource("/") == null;
        }
        return runInFatjar;
    }


    @Override
    public boolean renderFile(String target, HttpServletRequest request, HttpServletResponse response) {
        //是否在 fatjar 运行，如果不在 fatjar 运行，由 tomcat 或者 undertow 自行渲染
        if (!isRunInFatjar()) {
            return false;
        }
        // 如果在 fatjar 运行，需要自己来渲染该文件
        new FileRender(getFile(target)).setContext(request, response).render();
        return true;
    }


    public String getRootPath() {
        return rootPath;
    }

    public void setRootPath(String rootPath) {
        this.rootPath = rootPath;
    }

    public String getTargetPrefix() {
        return targetPrefix;
    }

    public void setTargetPrefix(String targetPrefix) {
        this.targetPrefix = targetPrefix;
        this.matchTarget = null;
    }
}

@@ -3422,24 +3422,102 @@
       return
+ !isRunInFatjar() //%E9%9D%9E fatjar %E6%A8%A1%E5%BC%8F%E4%B8%8B%EF%BC%8C%E8%AE%A9%E5%AE%B9%E5%99%A8%EF%BC%88tomcat %E6%88%96%E8%80%85 undertow%EF%BC%89%E5%8E%BB%E6%B8%B2%E6%9F%93%0A                &&
  target.star
@@ -3542,16 +3542,32 @@
 arget())
+%0A               
  && targ
@@ -4296,177 +4296,8 @@
 ) %7B%0A
-        //%E6%98%AF%E5%90%A6%E5%9C%A8 fatjar %E8%BF%90%E8%A1%8C%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%9C%A8 fatjar %E8%BF%90%E8%A1%8C%EF%BC%8C%E7%94%B1 tomcat %E6%88%96%E8%80%85 undertow %E8%87%AA%E8%A1%8C%E6%B8%B2%E6%9F%93%0A        if (!isRunInFatjar()) %7B%0A            return false;%0A        %7D%0A        // %E5%A6%82%E6%9E%9C%E5%9C%A8 fatjar %E8%BF%90%E8%A1%8C%EF%BC%8C%E9%9C%80%E8%A6%81%E8%87%AA%E5%B7%B1%E6%9D%A5%E6%B8%B2%E6%9F%93%E8%AF%A5%E6%96%87%E4%BB%B6%0A
     

optimize LocalAttachmentContainer