package jp.sourceforge.shovel.taglib;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import freemarker.template.utility.StringUtil;

public class NCREncodeTag extends TagSupport {
    static final long serialVersionUID = -1L;
    String data_;
    String escape_;
    
    enum EscapeType {
        XML("xml"),
        JSON("json");
        
        String type_;
        public String getType() {
            return type_;
        }
        public void setType(String type) {
            type_ = type;
        }
        EscapeType(String type) {
            type_ = type;
        }
        static public EscapeType find(String type) {
            if (type != null) {
                for (EscapeType escapeType : values()) {
                    if (type.compareToIgnoreCase(escapeType.getType()) == 0) {
                        return escapeType;
                    }
                }
            }
            return XML;
        }
        public boolean isXML() {
            return this == XML;
        }
        public boolean isJSON() {
            return this == JSON;
        }
    }
    
    public String getData() {
        return data_;
    }
    public void setData(String data) {
        data_ = data;
    }
    public String getEscape() {
        return escape_;
    }
    public void setEscape(String escape) {
        escape_ = escape;
    }
    public int doStartTag() throws JspException {
        try {
            if (data_ != null && data_.length() > 0) {
//                String data = StringUtil.HTMLEnc(data_);
                EscapeType escapeType = EscapeType.find(escape_);
                String header, footer;
                switch (escapeType) {
                default:
                case XML:
                    header = "&#"; //16進数
                    footer = ";";
                    break;
                case JSON:
                    header = "\\u";
                    footer = "";
                    break;
                }
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < data_.length(); i++) {
                    int ch = data_.codePointAt(i);
                    if (ch >= 0x00 && ch <= 0x1f || ch >= 0x20 && ch <= 0x7f) {
                        //ASCII
                        if (escapeType.isJSON() && ch == '/') {
                            builder.append("\\/");
                        } else {
                            String str = new String(Character.toChars(ch));
                            str = StringUtil.HTMLEnc(str);
                            builder.append(str);
//                            builder.append(Character.toChars(ch));
                        }
                    } else {
                        builder.append(header);
                        //マルチバイト
                        if (escapeType.isJSON()) {
                            //4桁16進数らしい
                            String hex = Integer.toHexString(ch);
                            int time = 4 - hex.length();
                            for (int j = 0;j < time; j++) {
                                builder.append("0");
                            }
                            builder.append(hex);
                        } else {
                            builder.append(ch);
                        }
                        builder.append(footer);
                    }
                }
                pageContext.getOut().print(builder.toString());
            }
        } catch (Exception e) {
            throw new JspException( e.getMessage() );
        }

        return SKIP_BODY;
    }
    public int doEndTag() {
        return EVAL_PAGE;
    }

}
