package cc.util.bossshop.filemanager;

import java.io.File;

import org.apache.commons.lang.Validate;

import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;

public abstract class AFileManager{

    // 静态全局变量
    /**
     * 配置文件版本节点
     */
    public static final String SEC_CFG_VERSION="version";
    // 普通变量
    /**
     * 主插件
     */
    protected final ABukkitPlugin mPlugin;
    /**
     * 管理器依赖的文件名
     */
    protected final String mFileName;
    /**
     * 管理器依赖的文件
     */
    protected File mFile;
    protected CommentedYamlConfig mConfig=new CommentedYamlConfig();
    /**
     * 配置文件版本
     */
    protected String mVersion="1.0";

    /**
     * 构造一个基于文件的管理器
     * @param pPlugin 主插件
     * @param pFileName 数据文件的相对路径
     */
    public AFileManager(ABukkitPlugin pPlugin,String pFileName,String pVersion){
        Validate.notNull(pFileName,"配置文件不能为空");
        this.mPlugin=pPlugin;
        this.mFileName=pFileName;
        this.mVersion=pVersion;
        this.mFile=new File(mPlugin.getDataFolder().getAbsolutePath(),mFileName);
    }

    /**
     * 重载配置文件
     * <p>
     * 如果文件不存在,自动创建文件<br />
     * 所有可能发生的错误都会被捕捉并显示在控制台<br />
     * </p>
     * @return 是否载入成功
     */
    public boolean reloadConfig(){
        if(!this.mConfig.loadFromFile(this.mFile)){
            this.severe("从文件"+this.mFileName+"载入配置失败,内存中配置未变化,目标文件未改动");
            return false;
        }
        return true;
    }

    /**
     * 保存config中的数据到到文件
     * <p>如果存在注释头部,将会同时保存注释头部</p>
     */
    public boolean saveConfig(){
        if(!this.mConfig.saveToFile(mFile)){
            this.severe("保存配置"+this.mFileName+"到文件失败,目标文件未改动");
            return false;
        }
        return true;
    }

    /**
     * 添加配置文件的默认值
     * <p>
     * 默认添加了版本<br />
     * 不应该在该函数中保存配置
     * </p>
     */
    protected void addDefaults(){
        this.mConfig.addDefault(AFileManager.SEC_CFG_VERSION,this.mVersion);
        this.mConfig.addDefaultComments(AFileManager.SEC_CFG_VERSION,"配置文件版本,重要,请勿修改","插件升级配置的时候需要用到");
    }

    /**
     * 检查配置文件版本是否需要更新,如果是则返回true
     * <p>请在实现类中的该方法中对文件进行更新操作</p>
     */
    protected boolean checkUpdate(){
        String tVersion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
        if(this.mVersion.compareToIgnoreCase(tVersion)<=0) return false;
        return true;
    }

    /**
     * 获取语言节点
     * @param pNode 节点名
     */
    protected String C(String pNode){
        return this.mPlugin.getLangManager().getNode(pNode);
    }

    /**
     * 获取该文件管理器的配置器
     */
    public CommentedYamlConfig getConfig(){
        return this.mConfig;
    }

    /**
     * 获取该文件管理器的文件名
     * @return
     */
    public String getConfigFilename(){
        return this.mFileName;

    }

    /**
     * 发送普通消息到控制台
     */
    public void info(String pMsg){
        this.mPlugin.info(pMsg);
    }

    /**
     * 发送消息到控制题啊
     * 添加消息到bug日志
     */
    public void warn(String pMsg){
        this.mPlugin.warn(pMsg);
    }

    /**
     * 输出错误消息到控制台
     * @param pMsg
     */
    public void severe(String pMsg){
        this.mPlugin.severe(pMsg);
    }

    /**
     * 输出调试信息
     * <p>如果配置文件中未启用调试,将不会输出信息</p>
     */
    public void debug(String message){
        this.mPlugin.debug(message);
    }

    /**
     * 输出错误消息到控制台,如果配置文件中启用调试模式,将会同时输出错误堆栈信息
     * @param pMsg 错误的消息
     * @param pExp 异常
     */
    public void severe(String pMsg,Exception pExp){
        this.mPlugin.severe(pMsg,pExp);
    }

}
