package cc.util.bossshop;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class JsonExtra{

    public enum HoverAction{
        show_text,show_item,show_achievement
    }

    public enum ClickAction{
        run_command,suggest_command,open_url
    }

    public enum Color{
        black('0'),
        dark_aqua('3'),
        dark_blue('1'),
        dark_gray('8'),
        dark_green('2'),
        dark_purple('5'),
        dark_red('4'),
        aqua('b'),
        blue('9'),
        gold('6'),
        gray('7'),
        green('a'),
        light_purple('d'),
        red('c'),
        white('f'),
        yellow('e');

        public static final char COLOR_CHAR='§';
        private final char code;
        private final String toString;

        private Color(char pChar){
            this.code=pChar;
            this.toString=new String(new char[]{'§',code});
        }
        
        @Override
        public String toString(){
            return this.toString;
        }
        
        public static boolean isColor(char c){
            return Color.getColor(c)!=null;
        }
        
        public static Color getColor(char c){
            c=(char)((c&0xDF)+32);
            for(Color sColor : Color.values())
                if(sColor.code==c) return sColor;
            return null;
        }

    }

    public enum Style{
        magic('k',null),
        bold('l',"bold"),
        strikethrough('m',"obfuscated"),
        underline('n',"underlined"),
        italic('o',"italic"),
        reset('r',null);
        
        public static final char FORMAT_CHAR='§';
        private final char code;
        private final String mLabel;
        private final String toString;

        private Style(char pChar,String pLabel){
            this.code=pChar;
            this.mLabel=pLabel;
            this.toString=new String(new char[]{'§',code});
        }

        @Override
        public String toString(){
            return this.toString;
        }
        
        public static boolean isStyle(char c){
           return Style.getStyle(c)!=null;
        }
        
        public static Style getStyle(char c){
            c=(char)((c&0xDF)+32);
            for(Style sStyle : Style.values())
                if(sStyle.code==c) return sStyle;
            return null;
        }
        
        /**
         * 如果为null代表这个是不是Json使用的节点
         */
        public String getJsonLabel(){
            return this.mLabel;
        }
        
    }

    private String mText="";
    private Color mTextColor=null;
    private JSONObject mHoverEvent=null;
    private JSONObject mClickEvent=null;
    private boolean mInherit=true;
    private static Pattern COLOR_FORMAT=Pattern.compile("§([0123456789AaBbCcDdEeFfKkLlMmNnOoRr])");
    private ArrayList<JsonExtra> mExtras=new ArrayList<>();
    /**未设置的值的格式默认继承,true或false代表是否启用,不允许put null*/
    private HashMap<Style,Boolean> mStyles=new HashMap<>();

    public JsonExtra(){
        this.mText="";
    }
    
    public JsonExtra(String pText){
        this.setText(pText);
    }

    public JsonExtra(String pText,Color pTextColor){
        this.setText(pText);
        this.setTextColor(pTextColor);
    }

    /**设置文字*/
    public void setText(String pText){
        if(pText==null) this.mText="";
        pText=ChatColor.translateAlternateColorCodes('&',pText);
        Color tcolor=this.mTextColor;
        ArrayList<JsonExtra> tChildExtrs=new ArrayList<>();
        HashMap<Style,Boolean> tStyles=new HashMap<>();
        tStyles.putAll(this.mStyles);
        Matcher matcher=COLOR_FORMAT.matcher(pText);
        int pos=0;
        while(matcher.find()){
            char cf=matcher.group(1).charAt(0);
            if(matcher.start()!=pos){
                JsonExtra te=new JsonExtra();
                te.mText=pText.substring(pos,matcher.start());
                te.mTextColor=tcolor;
                te.mStyles.putAll(tStyles);
                te.mInherit=false;
                tChildExtrs.add(te);
            }
            if(Color.isColor(cf)){
                tcolor=Color.getColor(cf);
                tStyles.clear();
            }else if(Style.isStyle(cf)){
                if(cf=='r'){
                    tcolor=null;
                    tStyles.clear();
                }else tStyles.put(Style.getStyle(cf),true);
            }
            pos=matcher.end();
        }
        JsonExtra te=new JsonExtra();
        te.mText=pText.substring(pos,pText.length());
        te.mTextColor=tcolor;
        te.mStyles.putAll(tStyles);
        te.mInherit=false;
        tChildExtrs.add(te);
        
        JsonExtra headExtra=tChildExtrs.remove(0);
        this.mText=headExtra.mText;
        this.mTextColor=headExtra.mTextColor;
        this.mStyles.clear();
        this.mStyles.putAll(headExtra.mStyles);
        this.mExtras.addAll(0,tChildExtrs);
    }

    /**设置文字颜色*/
    public void setTextColor(Color pTextColor){
        if(pTextColor==null) return;
        this.mTextColor=pTextColor;
    }

    /**
     * 设置字体样式
     */
    public void setStyle(Style...pStyles){
        if(pStyles==null) return;
        for(Style sStyle : pStyles)
            this.mStyles.put(sStyle,true);
    }
    
    /**
     * 移除字体样式
     */
    public void removeStyle(Style...pStyles){
        if(pStyles==null) return;
        for(Style sStyle : pStyles)
            this.mStyles.remove(sStyle);
    }

    /**
     * 清除所有格式
     */
    public void clearStyle(){
        this.mStyles.clear();
    }
    
    /**
     * 将所有样式设置为false
     */
    public void resetStyle(){
        for(Style sStyle : Style.values())
            this.mStyles.put(sStyle,false);
        this.mStyles.put(Style.reset,true);
    }
    
    /**
     * 设置是否继承父级的样式
     */
    public void setInherit(boolean pInherit){
        this.mInherit=pInherit;
    }

    /**
     *  是否继承父级的样式
     */
    public boolean isInherit(){
        return this.mInherit;
    }
    
    /**
     * 设置文字点击事件要执行的动作
     * @param pAction 动作类型
     * @param pValue 值
     */
    public void setClickEvent(ClickAction pAction,String pValue){
        if(pAction==null||StringUtils.isEmpty(pValue)) return;
        this.mClickEvent=new JSONObject();
        this.mClickEvent.put("action",pAction.name());
        this.mClickEvent.put("value",pValue);
    }

    /**
     * 设置文件在鼠标悬浮式要执行的动作
     * @param pAction 动作
     * @param pValue 值
     */
    public void setHoverEvent(HoverAction pAction,String pValue){
        if(pAction==null||StringUtils.isEmpty(pValue)) return;
        this.mHoverEvent=new JSONObject();
        this.mHoverEvent.put("action",pAction.name());
        this.mHoverEvent.put("value",pValue);
    }

    private JSONObject getJson(){
        JSONObject tJson=new JSONObject();
        tJson.put("text",this.mText);
        for(Style sStyle :Style.values()){
            if(sStyle.getJsonLabel()==null) continue;
            Boolean hasSet=this.mStyles.get(sStyle);
            if(hasSet==null){
                if(!this.mInherit) tJson.put(sStyle.getJsonLabel(),false);
            }else{
                tJson.put(sStyle.getJsonLabel(),hasSet.booleanValue());
            }
        }
        if(this.mTextColor!=null) tJson.put("color",this.mTextColor.name());
        if(this.mClickEvent!=null) tJson.put("clickEvent",this.mClickEvent);
        if(this.mHoverEvent!=null) tJson.put("hoverEvent",this.mHoverEvent);
        if(!this.mExtras.isEmpty()){
            JSONArray tJsonArray=new JSONArray();
            for(JsonExtra sExtra : this.mExtras){
                tJsonArray.add(sExtra.getJson());
            }
            tJson.put("extra",tJsonArray);
        }
        return tJson;
    }

    @Override
    public String toString(){
        return this.getJson().toJSONString();
    }
    
    @Override
    public JsonExtra clone(){
        JsonExtra clone=new JsonExtra(this.mText,this.mTextColor);
        JSONObject jsonObject=null;
        if(this.mClickEvent!=null){
            jsonObject=new JSONObject();
            jsonObject.putAll((Map<?,?>)this.mClickEvent.clone());
            clone.mClickEvent=jsonObject;
        }
        if(this.mHoverEvent!=null){
            jsonObject=new JSONObject();
            jsonObject.putAll((Map<?,?>)this.mHoverEvent.clone());
            clone.mHoverEvent=jsonObject;
        }
        clone.mInherit=this.mInherit;
        clone.mStyles.putAll(this.mStyles);
        for(JsonExtra childExtra : this.mExtras){
            clone.mExtras.add(childExtra.clone());
        }
        return clone;
    }

    public String toSimpleString(){
        StringBuilder tStr=new StringBuilder();
        if(this.mTextColor!=null) tStr.append(this.mTextColor.toString());
        for(Entry<Style,Boolean> entry : this.mStyles.entrySet())
            if(entry.getValue()) tStr.append(entry.getKey().toString());
        tStr.append(this.mText);
        for(JsonExtra sExtra : this.mExtras)
            tStr.append(sExtra.toSimpleString());
        return tStr.toString();
    }

    public void addExtra(JsonExtra pExtra){
        if(pExtra==null) return;
        this.mExtras.add(pExtra);
    }

    public void addNormalWords(String pWords,boolean pInherit){
        if(StringUtils.isEmpty(pWords)) return;
        JsonExtra tExtra=new JsonExtra(pWords,Color.white);
        if(!pInherit)
            tExtra.mInherit=false;
        this.addExtra(tExtra);
    }

    /**
     * 将Json消息发送给玩家<br />
     * 如果CommandSender不是玩家,将只发送非Json的消息串
     */
    public void sendToPlayer(CommandSender pSender){
        if(pSender instanceof Player){
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"tellraw "+((Player)pSender).getName()+" "+this.toString());
        }else pSender.sendMessage(this.toSimpleString());
        //System.out.println(this.toString());
    }

}
