package me.qwq.doghouse.pojo.bo;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;

import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
@Accessors(chain=true)
public class ThemeInfo {
    
    private static final ResourceLoader RESOURCE_LOADER =
            new DefaultResourceLoader();
    
    String name;
    
    String description;
    
    String author;
    
    String version;
    
    String link;
    
    /**
     * 原始目录, 最多统一到 file: 和 classpath:, 作为资源查找备用
     */
    String directory;
    
    /**
     * 模板拼接目录, 外部主题和 directory 一致, 内部主题则从 classpath:templates/ 下的路径开始
     */
    String templateDirectory;
    
    String folderName;
    
    @Setter(AccessLevel.PRIVATE)
    String identity;

    boolean internal;
    
    String image;
    
    protected ThemeInfo() {}
    
    public String getIdentity() {
        if (identity != null) return identity;
        identity = (internal ? "INTERNAL:" : "EXTERNAL:") + folderName;
        return identity;
    }
    
    /**
     * 获取模板路径
     * @param segment
     * @return
     */
    public String getTemplateString(String...segment) {
        String path = Paths.get(getTemplateDirectory(), segment).toString().replace('\\', '/');
        StringBuilder sb = new StringBuilder();
        if (!isInternal() && !StringUtils.startsWith(path, "file:")) {
            sb.append("file:");
        }
        sb.append(path);
        return sb.toString();
    }
    
    /**
     * 根据 HttpStatus 返回对应错误模板页面<p>
     * 该方法有 fallback 流程。假设 statusCode = 403
     * <li>优先匹配模板目录下 /error/error_403.html 并返回
     * <li>若不存在则尝试匹配 /error/error_4xx.html 并返回
     * <li>若不存在则直接返回 /error/error.html 并返回
     * 
     * @param status HTTP 错误状态码
     * @return
     */
    public String getErrorTemplateString(HttpStatus status) {
        String codeSpecificTemplate = getTemplateString("error", "error_" + status.value());
        if (templateExists(codeSpecificTemplate)) {
            return codeSpecificTemplate;
        }
        String familyTemplate = getTemplateString("error", "error_" + (status.value() / 100) + "xx");
        if (templateExists(familyTemplate)) {
            return familyTemplate;
        }
        return getTemplateString("error", "error");
    }
    
    /**
     * 判断模板是否存在
     * @param path 完整路径, 建议通过 {@link #getTemplateString(String...)} 获取
     * @return
     */
    private boolean templateExists(String path) {
        if (!StringUtils.endsWith(path, ".html")) {
            path += ".html";
        }
        if (isInternal()) {
            Resource r = RESOURCE_LOADER.getResource("classpath:templates/" + path);
            return r.exists();
        }
        else {
            Path p = Paths.get(path);
            return Files.isRegularFile(p);
        }
    }

}
