package org.black_ixx.bossshop.mail;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import java.util.Map.Entry;

import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.managers.ItemStackCreator;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.filemanager.AFileManager;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;

public class MailManager extends AFileManager implements INeedConfig,INeedReload{

    public static final String CFG_MAIN="MailSystem";
    public static final String SEC_ItemType="Type";
    public static final String SEC_ItemContent="Content";
    public static final String SEC_Source="Source";
    public static final String SEC_MaxSize="MaxSize";
    public static final String SEC_SendCost="SendCost";
    private int mMaxSize=10;
    private int mSendCost=1000;
    private final HashMap<UUID,ArrayList<MailItem>> mMailItems=new HashMap<>();
    private long mLastReloadTime=0;
    
    public MailManager(BossShop pPlugin){
        super(pPlugin,"mail_item.yml","1.0");
        this.mPlugin.registerConfigModel(this);
        this.mPlugin.registerReloadModel(this);
    }
    
    public long getLastReloadTime(){
        return this.mLastReloadTime;
    }
    
    @Override
    public void setConfig(){
        CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
        this.mMaxSize=tConfig.getInt(CFG_MAIN+"."+SEC_MaxSize,mMaxSize);
        this.mSendCost=tConfig.getInt(CFG_MAIN+"."+SEC_SendCost,mSendCost);
    }
    
    @Override
    public boolean reloadConfig(){
        if(!super.reloadConfig()) return false;
        this.mLastReloadTime=System.currentTimeMillis();
        this.loadMailItem();
        return true;
    }
  
    /**
     * 从配置文件中载入邮件物品
     */
    protected void loadMailItem(){
        this.mMailItems.clear();
        for(String player_key : this.mConfig.getKeys(false)){
            ConfigurationSection player_sec=this.mConfig.getConfigurationSection(player_key);
            if(player_sec==null){
                this.mConfig.set(player_key,null);
                continue;
            }
            UUID tUuid=null;
            try{
                tUuid=UUID.fromString(player_key);
            }catch(Exception exp){
                this.mPlugin.severe(ChatColor.RED+"配置文件["+this.mFileName+"]存在错误,["+player_key+"] 必须为UUID");
                continue;
            }
            ArrayList<MailItem> list=new ArrayList<>();
            for(String item_key : player_sec.getKeys(false)){
                try{
                    ConfigurationSection item_sec=player_sec.getConfigurationSection(item_key);
                    if(item_sec==null) continue;
                    BSBuyType tItemType=BSEnums.getBSBuyType(item_sec.getString(SEC_ItemType));
                    Object tItem=null;
                    if(tItemType==null){
                        this.warn(C("CFG.UnsupportMailItemType")+"["+item_sec.getString(SEC_ItemType)+"]");
                        continue;
                    }
                    switch(tItemType){
                    case Money:
                        tItem=item_sec.get(SEC_ItemContent);
                        break;
                    case Points:
                        tItem=item_sec.get(SEC_ItemContent);
                        break;
                    case Item:
                        tItem=((BossShop)this.mPlugin).getManager(ItemStackCreator.class).createItemStackS(item_sec.getStringList(SEC_ItemContent),false);
                        if(tItem==null){
                            this.warn(C("CannotCreatMailItem"));
                            continue;
                        }
                        break;
                    default:
                        this.warn(C("CFG.UnsupportMailItemType")+"["+tItemType.name()+"]");
                        continue;
                    }
                    list.add(new MailItem(tItem,tItemType,1,item_sec.getString(SEC_Source)));
                    if(list.size()>=this.mMaxSize) break;
                }catch(Exception exp){
                    this.mPlugin.severe(exp.getMessage(),exp);
                }
            }
            this.mMailItems.put(tUuid,list);
        }
    }

    /**
     * 添加一封来自他人的邮件,调用前请先检查邮件是否已经满了
     * <p>如果玩家在线,会提醒玩家有新邮件</p>
     * @param pFrom 来自谁
     * @param pTo 给谁
     * @param pItem 物品
     */
    public MailItem addMail(Player pFrom,Player pTo,ItemStack pItem){
        MailItem tItem=new MailItem(pItem,BSBuyType.Item,1,C("Mail.FromPlayer")+pFrom.getName());
        if(!this.addMailToFile(pTo.getUniqueId(),tItem)) return null;
        this.addMail(pTo.getUniqueId(),tItem);
        return tItem;
    }
    
    /**
     * 添加过期物品到邮件列表,如果玩家在线会发送提醒
     * @return 失败返回空
     */
    public MailItem addMail(BSBuy pBuy,String pSource){
        if(!pBuy.hasOwner()||pBuy.getLimit()<=0) return null;
        if(this.isMailFull(pBuy.getOwner())){
            this.noticeMailFull(pBuy.getOwner());
            return null;
        }
        MailItem tItem=new MailItem(pBuy.getReward(),pBuy.getBuyType(),pBuy.getLimit(),pSource);
        if(!this.addMailToFile(pBuy.getOwner(),tItem)) return null;
        this.addMail(pBuy.getOwner(),tItem);
        return tItem;
    }
    
    /**
     * 添加邮件到邮件列表,调用前必须检查isMailFull<br />
     * 在此函数中统一发送通知消息
     */
    private void addMail(UUID pUUID,MailItem pItem){
        ArrayList<MailItem> tItems=this.mMailItems.get(pUUID);
        if(tItems==null){
            tItems=new ArrayList<>();
            this.mMailItems.put(pUUID,tItems);
        }
        tItems.add(pItem);
        Player tPlayer=Bukkit.getPlayer(pUUID);
        if(tPlayer!=null&&tPlayer.isOnline()){
            this.mPlugin.send(tPlayer,C("Mail.YouReciveMail").replace("%where%",pItem.getSource()));
            //tPlayer.playSound(tPlayer.getLocation(),org.bukkit.Sound.ENTITY_PLAYER_LEVELUP,1,1);
        }
    }
    
    /**
     * 玩家邮箱是否达到了数量上限
     */
    public boolean isMailFull(UUID pUUID){
        if(this.mMaxSize<=0) return true;
        ConfigurationSection tUserSec=this.mConfig.getConfigurationSection(pUUID.toString());
        if(tUserSec==null) return false;
        return tUserSec.getKeys(false).size()>=this.mMaxSize;
    }
    
    /**
     * 通知玩家邮箱已经满了
     * @param pUUID
     */
    public void noticeMailFull(UUID pUUID){
        Player tPlayer=Bukkit.getPlayer(pUUID);
        if(tPlayer==null||!tPlayer.isOnline()) return;
        this.mPlugin.send(tPlayer,C("YouMailIsFull"));
    }
    
    public void noticeExistMail(Player pPlayer){
        if(pPlayer==null||!pPlayer.isOnline()) return;
        int mailCount=this.getMailCount(pPlayer.getUniqueId());
        if(mailCount<=0) ;//TODO 你没有邮件
        else ; //TODO 你有邮件
    }
    
    /**
     * 添加邮件到文件,调用前必须检查isMailFull
     * @param pUUID 玩家UUID
     * @param pItem 邮件
     */
    protected boolean addMailToFile(UUID pUUID,MailItem pItem){
        ConfigurationSection tUserSec=this.mConfig.getConfigurationSection(pUUID.toString());
        if(tUserSec==null) tUserSec=this.mConfig.createSection(pUUID.toString());
        long time=System.currentTimeMillis()/1000;
        String tItemLabel="item_"+time;
        while(tUserSec.contains(tItemLabel))
            tItemLabel="item_"+(++time);
        ConfigurationSection tItemSec=tUserSec.createSection(tItemLabel);
        tItemSec.set(SEC_ItemType,pItem.getItemType().name());
        switch(pItem.getItemType()){
        case Money:
        case Points:
            tItemSec.set(SEC_ItemContent,pItem.getItem());
            break;
        case Item:
            ItemStack item=(ItemStack)pItem.getItem();
            ArrayList<String> tItemInfo=new ArrayList<>();
            tItemInfo.add("id:"+item.getTypeId());
            tItemInfo.add("durability:"+item.getDurability());
            tItemInfo.add("amount:"+item.getAmount());
            String nbtlabel=((BossShop)this.mPlugin).getManager(NBTEditManager.class).addItemNBTToStock(item,true);
            if(nbtlabel!=null) tItemInfo.add("nbt:"+nbtlabel);
            tItemSec.set(SEC_ItemContent,tItemInfo);
            break;
        default:
            this.warn(ChatColor.RED+"["+pItem.getItemType().name()+"]");
            this.warn(C("Mail.UnsupportMailItemType"));
            tUserSec.set(tItemLabel,null);
            return false;
        }
        tItemSec.set(SEC_Source,pItem.getSource());
        this.saveConfig();
        return true;
    }

    /**
     * 返回玩家所有过期几首物品的预览
     * @param pUUID 玩家UUID
     * @return 过期物品预览列表,或没有邮件的消息
     */
    public ArrayList<String> checkMail(UUID pUUID){
        ArrayList<String> items_preview=new ArrayList<>();
        for(Entry<UUID,ArrayList<MailItem>> entry : this.mMailItems.entrySet()){
            if(entry.getKey().equals(pUUID)){
                int i=1;
                for(MailItem sitem : entry.getValue()){
                    items_preview.add(i+". "+sitem.getPreview());
                    i++;
                }
                break;
            }
        }
        if(items_preview.size()!=0){
            items_preview.add(0,C("Mail.MailMaxSaveNumb").replace("%numb%",items_preview.size()+"/"+this.mMaxSize));
            items_preview.add(items_preview.size(),"====================");
        }else items_preview.add(C("Mail.YouHaveNoMail"));
        return items_preview;
    }

    public int getMailCount(UUID pUUID){
        for(Entry<UUID,ArrayList<MailItem>> entry : this.mMailItems.entrySet()){
            if(entry.getKey().equals(pUUID)){
                return entry.getValue().size();
            }
        }
        return 0;
    }
    
    /**
     * 返还寄售过期的物品
     */
    public void reciveMail(Player player){
        if(player==null) return;
        UUID tUuid=player.getUniqueId();
        WorthHandler wHandler=((BossShop)this.mPlugin).getManager(WorthHandler.class);
        for(UUID key : this.mMailItems.keySet()){
            if(key.equals(tUuid)){
                boolean tIsItem=false;
                for(MailItem item : this.mMailItems.get(key)){
                    switch(item.getItemType()){
                    case Money:
                        wHandler.giveRewardMoney(player,(Integer)item.getItem());
                        break;
                    case Points:
                        wHandler.giveRewardPoints(player,(Integer)item.getItem());
                        break;
                    case Item:
                        tIsItem=true;
                        wHandler.giveRewardItem(player,(ItemStack)item.getItem());
                        break;
                    default:
                        break;
                    }
                    this.mPlugin.send(player,ChatColor.GREEN+C("Word.Revive")+item.getPreview());
                }
                if(tIsItem&&((BossShop)this.mPlugin).getConfigManager().isAutoClearNBT())
                    ((BossShop)this.mPlugin).getManager(NBTEditManager.class).clearNBT();
                this.mMailItems.remove(key);
                this.mConfig.set(tUuid.toString(),null);
                this.saveConfig();
                return;
            }
        }
    }

    public int getMailSendCost(){
        return this.mSendCost;
    }
    
}
