package org.black_ixx.bossshop.sale;

import java.util.HashMap;

import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;

import cc.util.bossshop.JsonExtra;
import cc.util.bossshop.JsonExtra.ClickAction;
import cc.util.bossshop.JsonExtra.Color;
import cc.util.bossshop.JsonExtra.HoverAction;
import cc.util.bossshop.JsonExtra.Style;


public class SaleListener implements Listener{

    private BossShop mPlugin;
    private HashMap<Player,SaleParameter> mForSale=new HashMap<>();

    public SaleListener(BossShop pPlugin){
        this.mPlugin=pPlugin;
        this.mPlugin.getServer().getPluginManager().registerEvents(this,this.mPlugin);
    }
 
    private String C(String pNode){
        return this.mPlugin.C(pNode);
    }
    
    @EventHandler(priority=EventPriority.LOW)
    public void onPlayerChat(AsyncPlayerChatEvent pEvent){
        synchronized(this){
            if(!this.needHandle(pEvent.getPlayer(),pEvent.getMessage())) return;
            pEvent.setCancelled(true);
            this.handlePlayerMsg(pEvent.getPlayer(),pEvent.getMessage());
        }
    }
    
    protected boolean needHandle(Player sender,String pMsg){
        if(sender==null||StringUtils.isEmpty(pMsg)) return false;
        if(pMsg.startsWith("/")) return false; //跳过命令
        SaleParameter tParam=this.mForSale.get(sender);
        if(tParam==null) return false;
        if(tParam.mStep==SaleStep.Finish){
            this.stopSaleListenrer(sender);
            return false;
        }
        return true;
    }
    
    /**
     * 处理玩家发送的消息
     * <p>调用前,请先使用{@link SaleListener#needHandle(Player, String)}检查是否因该处理</p>
     * @param pSender 消息发送者
     * @param pMsg 发送的消息
     */
    protected void handlePlayerMsg(Player pSender,String pMsg){
        SaleParameter tParam=this.mForSale.get(pSender);
        if(this.handleStep(pSender,tParam,pMsg)){
            tParam.mStep=SaleStep.getNext(tParam.mStep);
        }
        this.showStepIntroduce(pSender,tParam);
        if(tParam.mStep==SaleStep.Finish)
            this.mForSale.remove(pSender);
    }
    
    public SaleParameter stopSaleListenrer(Player pPlayer){
        SaleParameter removeParam= this.mForSale.remove(pPlayer);
        if(removeParam==null){
            //this.mPlugin.send(pPlayer,"你没有开始寄售");
        }else{
            this.mPlugin.send(pPlayer,C("Sale.ChatSaleExit"));
        }
        return removeParam;
    }
    
    public void startSaleListenrer(Player pPlayer){
        SaleParameter tp=this.mForSale.get(pPlayer);
        if(tp!=null){
            if(tp.mStep==SaleStep.Finish){
                tp.mStep=SaleStep.GoodsType;
            }else{
                this.mPlugin.send(pPlayer,C("Sale.ChatSaleRepartStart"));
                return;
            }
        }else{
            tp=new SaleParameter();
            this.mForSale.put(pPlayer,tp);
        }
        this.mPlugin.send(pPlayer,C("Sale.ChatSaleStart"));
        this.showStepIntroduce(pPlayer,tp);
    }
    
    /**
     * 显示当前寄售步奏的提示
     * @param pPlayer 用户名
     * @param pStep 参数
     */
    public void showStepIntroduce(Player pPlayer,SaleParameter pParam){
        switch(pParam.mStep){
        case GoodsType:
            this.showSelect(pPlayer,this.mPlugin.getChatPrefix()+" "+C("Sale.IntroduceSellType")
                    ,new String[]{C("Word.Item"),C("Word.Money"),C("Word.Points")}
                    ,new String[]{"item","money","points"}
            );
            break;
        case SingleNumb:
            this.mPlugin.send(pPlayer,C("Sale.IntroduceSingleNumb"));
            break;
        case PartNumb:
            this.mPlugin.send(pPlayer,C("Sale.IntroducePartNumb"));
            break;
        case PriceType:
            this.showSelect(pPlayer,this.mPlugin.getChatPrefix()+" "+C("Sale.IntroducePriceType")
                    ,new String[]{C("Word.Money"),C("Word.Points")}
                    ,new String[]{"money","points"}
            );
            break;
        case Price:
            this.mPlugin.send(pPlayer,C("Sale.IntroducePrice"));
            break;
        case Finish:
            this.mPlugin.send(pPlayer,C("Sale.ChatSaleFinish"));
            JsonExtra chat=new JsonExtra(this.mPlugin.getChatPrefix()+" "+C("Sale.ClickSaleButtonFor"));
            JsonExtra saleButton=new JsonExtra(C("Word.ForSale"),Color.blue);
            saleButton.setStyle(Style.bold,Style.underline);
            saleButton.setClickEvent(ClickAction.run_command,this.getSaleCommand(pParam));
            saleButton.setHoverEvent(HoverAction.show_text,this.getSaleHover(pParam));
            chat.addExtra(saleButton);
            chat.sendToPlayer(pPlayer);
            break;
        }
    }
    
    private String getSaleCommand(SaleParameter pParam){
        StringBuilder builder=new StringBuilder("/BS sale ");
        builder.append(pParam.saleType.name()+" ");
        builder.append(pParam.singleNumb+" ");
        builder.append(pParam.partNumb+" ");
        builder.append(pParam.priceType.name()+" ");
        builder.append(pParam.price);
        return builder.toString();
    }
    
    private String getSaleHover(SaleParameter pParam){
        String color=C("Sale.NowSaleParameterColor");
        if(!color.startsWith("§")) color="§a"; 
        StringBuilder builder=new StringBuilder(color+C("Sale.NowSaleParameter")+"\n");
        builder.append(color+C("Word.SellType")+": "+C("Word."+pParam.saleType.name())+"\n");
        builder.append(color+C("Word.SigleNumb")+": "+pParam.singleNumb+"\n");
        builder.append(color+C("Word.PartNumb")+": "+pParam.partNumb+"\n");
        builder.append(color+C("Word.Price")+": "+pParam.price+C("Word."+pParam.priceType.name()));
        return builder.toString();
    }
    
    /**
     * 处理当前寄售步奏的玩家输入
     * <p>
     * 错误消息会在本函数中立刻显示
     * </p>
     * @param pPlayer 用户名
     * @param pParam 已经处理的参数
     * @param pMsg 当前参数的输入
     * @return 是否处理成功
     */
    public boolean handleStep(Player pPlayer,SaleParameter pParam,String pMsg){
        SaleManager saleMan=this.mPlugin.getManager(SaleManager.class);
        boolean result=false;
        String successMsg=C("Sale.YouSetSaleParamTo");
        switch(pParam.mStep){
        case GoodsType:
            if(!(result=saleMan.handleGoodsTypeInput(pParam,pPlayer,pMsg)))
                this.mPlugin.send(pPlayer,pParam.errorInfo);
            else{
                successMsg=successMsg.replace("%param%",C("Word.SellType")).replace("%value%",C("Word."+pParam.saleType.name()));
                this.mPlugin.send(pPlayer,successMsg);
            }
            return result;
        case SingleNumb:
            if(!(result=saleMan.handleSingleNumbInput(pParam,pPlayer,pMsg)))
                this.mPlugin.send(pPlayer,pParam.errorInfo);
            else{
                successMsg=successMsg.replace("%param%",C("Word.SigleNumb")).replace("%value%",pParam.singleNumb+"");
                this.mPlugin.send(pPlayer,successMsg);
            }
            return result;
        case PartNumb:
            if(!(result=saleMan.handlePartNumbInput(pParam,pPlayer,pMsg)))
                this.mPlugin.send(pPlayer,pParam.errorInfo);
            else{
                successMsg=successMsg.replace("%param%",C("Word.PartNumb")).replace("%value%",pParam.partNumb+"");
                this.mPlugin.send(pPlayer,successMsg);
            }
            return result;
        case PriceType:
            if(!(result=saleMan.handlePriceTypeInput(pParam,pPlayer,pMsg)))
                this.mPlugin.send(pPlayer,pParam.errorInfo);
            else{
                successMsg=successMsg.replace("%param%",C("Word.PriceType")).replace("%value%",C("Word."+pParam.priceType.name()));
                this.mPlugin.send(pPlayer,successMsg);
            }
            return result;
        case Price:
            if(!(result=saleMan.handlePriceInput(pParam,pPlayer,pMsg)))
                this.mPlugin.send(pPlayer,pParam.errorInfo);
            else{
                successMsg=successMsg.replace("%param%",C("Word.Price")).replace("%value%",pParam.price+"");
                this.mPlugin.send(pPlayer,successMsg);
            }
            return result;
        case Finish:
            throw new IllegalArgumentException("在聊天栏寄售状态为Finish时,不能处理输入参数");
        }
        return false;
    }
    
    /**
     * 使用指定参数显示一个可点击的选项消息
     * @param pPlayer 发送给谁
     * @param pMsg 消息前缀
     * @param pSelectDisName 选项显示名字
     * @param pSelect 选项值
     */
    protected void showSelect(Player pPlayer,String pMsg,String[] pSelectDisName,String[] pSelect){
        JsonExtra main=new JsonExtra(pMsg);
        JsonExtra goosType=new JsonExtra("",Color.gold);
        goosType.setStyle(Style.bold,Style.underline);
        for(int i=0;i<pSelectDisName.length;i++){
            JsonExtra detailGoodsType=goosType.clone();
            detailGoodsType.setText(pSelectDisName[i]);
            detailGoodsType.setClickEvent(ClickAction.run_command,pSelect[i]);
            detailGoodsType.setHoverEvent(HoverAction.show_text,Color.gold+pSelect[i]);
            main.addExtra(detailGoodsType);
            if(i!=pSelectDisName.length-1)
                main.addNormalWords(", ",true);
        }
        main.sendToPlayer(pPlayer);
    }
}
