package org.nutz.mvc.adaptor.injector;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 对象路径节点转换.<br/>
 * 将URL中的字符串参数名转换成对结构, 然后通过 {@link org.nutz.mapl.Mapl}转换成实体对象<br/>
 * URL规则:
 * <ul>
 *  <li>对象与属性之间使用"."做为连接符
 *  <li>数组,Collection对象, 使用"[]"或":"做为索引引用符. <b style='color:red'>索引只是一个参考字段, 不会根据其值设置索引</b>
 *  <li>Map使用"()"或"."分割key值
 * </ul>
 * 例:<br> 
 * <code>
 * Object:  node.str = str<br>
 * list:    node.list[1].str = abc;<br>
 *          node.list:2.str = 2<br>
 * set:     node.set[2].str = bbb<br>
 *          node.set:jk.str = jk<br>
 * Map:     node.map(key).str = bb;<br>
 *          node.map.key.name = map<br>
 * 
 * </code>
 * @author juqkai(juqkai@gmail.com)
 *
 */
public class ObjectNaviNode {
    private static final char separator = '.';
    private static final char LIST_SEPARATOR = ':';
    private static final int TYPE_NONE = 0;
    private static final int TYPE_LIST = 1;
    //节点名
    private String name;
    //叶子节点的值
    private String[] value;
    //是否是叶子节点
    private boolean leaf = true;
    //子节点
    private Map<String, ObjectNaviNode> child = new HashMap<String, ObjectNaviNode>();
    //类型
    private int type = TYPE_NONE;

    /**
     * 初始化当前结点
     * 
     */
    public void put(String path, String[] value) {
        StringBuilder sb = new StringBuilder();
        char[] chars = path.toCharArray();
        OUT: for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            switch (c) {
            case '[':
            case '(':
                i++;
                StringBuilder sb2 = new StringBuilder();
                boolean isNumber = true;
                for (; i < chars.length; i++) {
                    char c2 = chars[i];
                    switch (c2) {
                        case ']':
                        case ')':
                            if ((c == '[' && c2 == ']') || (c == '(' && c2 == ')')) {
                                if (isNumber && !(c == '(')) {
                                    sb.append(':').append(sb2);
                                } else {
                                    sb.append('.').append(sb2);
                                }
                                continue OUT;
                            }
                        default:
                    }
                    isNumber = isNumber && Character.isDigit(c2);
                    sb2.append(c2);
                }
                break;
            default:
                sb.append(c);
                break;
            }
        }
        path = sb.toString();
        putPath(path, value);
    }
    
    private void putPath(String path, String[] value){
        init(path);
        String subPath = fetchSubPath(path); 
        if ("".equals(subPath) || path.equals(subPath)) {
            this.value = value;
            return;
        }
        leaf = false;
        addChild(subPath, value);
    }
    /**
     * 添加子结点
     * 
     */
    private void addChild(String path, String[] value) {
        String subname = fetchName(path);
        ObjectNaviNode onn = child.get(subname);
        if (onn == null) {
            onn = new ObjectNaviNode();
        }
        onn.putPath(path, value);
        child.put(subname, onn);
    }
    
    /**
     * 初始化name, type信息
     * @param path
     */
    private void init(String path){
        String key = fetchNode(path);
        if(isList(key)){
            type = TYPE_LIST;
            name = key.substring(0, key.indexOf(LIST_SEPARATOR));
            return;
        }
        name = key;
    }
    
    /**
     * 提取子路径
     * @param path
     */
    private String fetchSubPath(String path){
        if(isList(fetchNode(path))){
            return path.substring(path.indexOf(LIST_SEPARATOR) + 1);
        }
        return path.substring(path.indexOf(separator) + 1);
    }
    

    
    /**
     * 取得节点名
     * 
     */
    private static String fetchNode(String path) {
        if (path.indexOf(separator) <= 0) {
            return path;
        }
        return path.substring(0, path.indexOf(separator));
    }
    
    
    /**
     * 取得节点的name信息
     */
    private String fetchName(String path){
        String key = fetchNode(path);
        if(isList(key)){
            return key.substring(0, key.indexOf(LIST_SEPARATOR));
        }
        return key;
    }
    
    /**
     * 提取出list,map结构
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Object get(){
        if(isLeaf()){
            return value == null ? null : value.length == 1 ? value[0] : value;
        }
        if(type == TYPE_LIST){
            // fix issue #1109, 列表的key需要重排
            List list = new ArrayList();
            List<Integer> keys = new ArrayList<Integer>();
            List<String> keys2 = new ArrayList<String>();
            
            for (String key : child.keySet()) {
                try {
                    keys.add(Integer.parseInt(key));
                }
                catch (NumberFormatException e) {
                    keys2.add(key);
                }
            }
            Collections.sort(keys);
            for(Integer index : keys){
                list.add(child.get(index.toString()).get());
            }
            for(String key2 : keys2){
                list.add(child.get(key2).get());
            }
            return list;
        }
        Map map = new HashMap();
        for(String o : child.keySet()){
            map.put(o, child.get(o).get());
        }
        return map;
    }
    
    /**
     * 是否是list节点
     * @param key
     */
    private static boolean isList(String key){
        return key.indexOf(LIST_SEPARATOR) > 0;
    }

    public String getName() {
        return name;
    }

    public String[] getValue() {
        return value;
    }

    public boolean isLeaf() {
        return leaf;
    }
}
