package cc.util.bossshop.pluginmodel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

import cc.util.bossshop.filemanager.AConfigManager;
import cc.util.bossshop.filemanager.ALangManager;
import me.clip.placeholderapi.PlaceholderAPI;

public abstract class ABukkitPlugin extends JavaPlugin{

    /**
     * 插件消息前缀
     */
    protected String prefix="§c[§7Templet§c]§b";
    /**
     * 插件日志前缀
     */
    protected String logpre="[Templet]";
    /**
     * 插件实例
     */
    protected static ABukkitPlugin mInstance;
   
    protected String mPluginName;
    
    /**
     * 可重置状态模块实例列表
     */
    protected ArrayList<IClearAble> mClearModel=new ArrayList<>();
    /**
     * 需要重新读取配置的模块列表,此列表模块将在配置文件重载后调用重载方法
     */
    protected ArrayList<INeedConfig> mConfigModels=new ArrayList<>();
    
    /**
     * 需要重载的模块列表,此列表模块将在配置文件重载后调用重载方法
     */
    protected ArrayList<INeedReload> mReloadModels=new ArrayList<>();
    /**
     * 配置管理器,需要初始化
     */
    protected AConfigManager mConfigManager;
    /**
     * 语言管理器,需要初始化
     */
    protected ALangManager mLangManager;
    
    /**
     * 新建一个插件实例
     * <p>
     * 同时会设置静态mInstance变量的值<br />
     * 实例化该对象后,请注意同时实例化语言文件和配置文件
     * </p>
     */
    public ABukkitPlugin(String pPluginName){
        ABukkitPlugin.mInstance=this;
        this.mPluginName=pPluginName;
        this.logpre="["+pPluginName+"]";
        this.prefix="§c[§7"+pPluginName+"§c]§b";
    }
    
    /**
     * 获取插件实例<br />
     * 不建议在static模块中初始化的时候调用此方法
     */
    private static ABukkitPlugin getInstance(){
        return ABukkitPlugin.mInstance;
    }
    
    /**
     * 获取语言翻译
     */
    public String C(String pNode){
        return this.mLangManager.getNode(pNode);
    }
    
    /**
     * 获取插件名字,用于构造命令,权限等
     */
    public String getPluginName(){
        return this.mPluginName;
    }
    
    /**
     * 聊天前缀
     */
    public String getChatPrefix(){
        return this.prefix;
    }
    
    /**
     * log日志前缀
     */
    public String getLogPrefix(){
        return this.logpre;
    }
    
    /**
     * 请使用{@link ABukkitPlugin#getConfigManager()#getConfig()}<br />
     * 调用此方法将抛出异常
     * 
     */
    @Deprecated
    public FileConfiguration getConfig(){
        throw new IllegalAccessError("请不不要调用此方法");
    }
    
    /**
     * 获取插件配置管理器
     */
    public AConfigManager getConfigManager(){
        return this.mConfigManager;
    }
    
    /**
     * 获取插件语言管理器
     */
    public ALangManager getLangManager(){
        return this.mLangManager;
    }
    
    /**
     * 重载插件
     */
    public abstract void reloadPlugin();
    
    /**
     * 清理插件可清理模块列表
     * @return 清理的模块数量
     */
    public int clearModelStatus(){
        int tCount=0;
        for(IClearAble sClearModel : this.mClearModel){
            if(sClearModel.clearStatus()) tCount++;
        }
        return tCount;
    }

    /**
     * 注册可清理状态模块列表
     */
    public void registerClearModel(IClearAble pClearModel){
        if(this.mClearModel.contains(pClearModel)) return;
        this.mClearModel.add(pClearModel);
    }
    
    /**
     * 注册需要重载配置的模块列表,此列表只用于非重要实例使用
     */
    public void registerConfigModel(INeedConfig pNeedConfig){
        if(this.mConfigModels.contains(pNeedConfig)) return;
        this.mConfigModels.add(pNeedConfig);
    }
    
    /**
     * 注册需要重载配置的模块列表,此列表只用于非重要实例使用
     */
    public void registerReloadModel(INeedReload pNeedReload){
        if(this.mReloadModels.contains(pNeedReload)) return;
        this.mReloadModels.add(pNeedReload);
    }
    
    /**
     * 移除可清理状态模块列表
     * @return 如果存在并移除返回true,不存在返回false
     */
    public boolean unregisterClearModel(IClearAble pClearModel){
        return this.mClearModel.remove(pClearModel);
    }
    
    /**
     * 移除可重载模块列表
     * @return 如果存在并移除返回true,不存在返回false
     */
    public boolean unregisterReloadModel(INeedConfig pReloadModel){
        return this.mConfigModels.remove(pReloadModel);
    }
    
    /**
     * 禁用此方法,请使用{@link ABukkitPlugin #reloadPlugin()}方法重载插件
     */
    @Deprecated
    @Override
    public void reloadConfig(){}
    
    /**
     * 发送消息到指定玩家
     * @param pSender 发送给谁
     * @param pMsg 消息,不需要加前缀
     * @return true
     */
    public boolean send(CommandSender pSender,String pMsg){
        return this.send(pSender,pMsg,prefix);
    }

    /**
     * 发送普通的Console消息
     * @param pMsg 消息,不需要加前缀
     */
    public void info(String pMsg){
        this.send(Bukkit.getConsoleSender(),pMsg,prefix);
    }

    /**
     * 发送警告的Console消息,暗红色消息
     * @param pMsg 消息,不需要加前缀
     */
    public void warn(String pMsg){
        this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.DARK_RED+"[WARN]");
    }

    /**
     * 发送错误的Console消息,暗红色消息
     * @param pMsg 消息,不需要加前缀
     */
    public void severe(String pMsg){
        this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[ERROR]");
    }

    /**
     * 输出错误信息到Console
     * <p>如果配置文件启用调试模式,会同时发送错误堆栈</p>
     * @param pMsg 消息
     * @param pExp 异常
     */
    public void severe(String pMsg,Throwable pExp){
        this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[ERROR]");
        if(!this.getConfigManager().isDebug()){
            this.severe("配置文件启用调试模式以看到更多错误消息");
            return;
        }
        String[] lines= org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(pExp).split("(\r?\n)+");
        for(String sLine : lines)
            this.debug(sLine);
    }

    /**
     * 输出调试信息到,红色
     * @param pMsg 消息
     */
    public void debug(String pMsg){
        if(!this.getConfigManager().isDebug()) return;
        send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[DEBUG]");
    }

    /**
     * 向用户发送消息
     * @param pSender 目标
     * @param pMsg 消息
     * @param pPrefix 消息前缀
     * @return true
     */
    public boolean send(CommandSender pSender,String pMsg,String pPrefix){
        if(StringUtils.isBlank(pMsg)) return true;
        if(pSender==null) pSender=Bukkit.getConsoleSender();
        pMsg=ChatColor.translateAlternateColorCodes('&',pMsg);
        pPrefix=ChatColor.translateAlternateColorCodes('&',pPrefix);
        if(pSender instanceof Player&&Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")){
            pMsg=PlaceholderAPI.setPlaceholders((Player)pSender,pMsg);
            pPrefix=PlaceholderAPI.setPlaceholders((Player)pSender,pPrefix);
        }
        List<String> tMsgs=Arrays.asList(pMsg.split("\n+"));
        for(String sMsg : tMsgs)
            pSender.sendMessage(pPrefix+" "+sMsg);
        return true;
    }

}
