package org.nutz.mapl.impl.convert;

import java.io.Reader;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.Streams;
import org.nutz.mapl.MaplConvert;
import org.nutz.mapl.impl.MaplEach;
import org.nutz.mapl.impl.MaplRebuild;

/**
 * MapList结构转换.
 * <p> 将一种MapList结构转换成另外一种MapList结构.例:
 * <pre>
 *  {
 *      "age":"123",
 *      "name":"juqkai"
 *  }
 *  转换成:
 *  {
 *      "年龄":"123",
 *      "姓名":"juqkai"
 *  }
 * </pre>
 * <p>要进行这样的转换需要预先配置一个对应关系的配置, 具体的配置关系说明如下:
 * <ul>
 * <li>使用原MapList一样的结构
 * <li>有数组的, 只写第一个元素的结构
 * <li>原结构中的值, 以字符串或字符串数组做为目标结构的对应关系
 * <li>对应关系可以为数组
 * <li>有数组的, 目标结构以key[].abc来代替数组
 * <li>原结构数组层次强制限定一致, 目标结构中'[]'的索引按原结构中出现先后顺序进行匹配.
 * <li>如果原结果不存在, 那默认为0
 * <li>未在模板中申明的不做转换
 * </ul>
 * <p> 例:
 * <pre>
 * 例1:
 *  {
 *      "age":"user.年龄",
 *      "name":["user.name", "user.姓名"]
 *  }
 * 例2(原json:[{"name":"nutz"},{"name":"juqkai"}]):
 * [{
 *      "name":"[].姓名"
 * }]
 * 例3:
 * {
 *      users:[
 *          {
 *              "name":["people[].name", "users[].name"],
 *              "age":"users[].name"
 *          }
 *      ]
 * }
 * </pre>
 * @author juqkai(juqkai@gmail.com)
 */
public class StructureConvert extends MaplEach implements MaplConvert{
    //关系
    private Map<String, List<String>> relation = new LinkedHashMap<String, List<String>>();
    
    private MaplRebuild structure = new MaplRebuild();
    
    /**
     * 
     * @param path 模板文件路径
     */
    public StructureConvert(String path){
        Object obj = Json.fromJson(Streams.fileInr(path));
        loadRelation(obj, "");
    }
    /**
     * 
     * @param reader 模板流
     */
    public StructureConvert(Reader reader){
        Object obj = Json.fromJson(reader);
        loadRelation(obj, "");
    }
    /**
     * 
     * @param obj 模板的Map, List结构
     */
    public StructureConvert(Object obj){
        loadRelation(obj, "");
    }
    
    /**
     * 转换
     * @param obj 目标对象
     */
    @Override
    public Object convert(Object obj){
        each(obj);
        return structure.fetchNewobj();
    }
    
    @Override
    protected void LRD(String path, Object item) {}

    /**
     * 重建新对象
     */
    @Override
    protected void DLR(String path, Object object) {
        if(relation.containsKey(path)){
            List<String> dests = relation.get(path);
            for(String dest : dests){
                if("".equals(dest)){
                    structure.put(path, object, arrayIndex);
                    continue;
                } 
                structure.put(dest, object, arrayIndex);
            }
        }
    }
    
    /**
     * 解析配置信息
     * @param obj
     * @param path
     */
    private void loadRelation(Object obj, String path) {
        if(obj instanceof Map){
            loadMapRelation((Map<?, ?>) obj, path);
        } else if(obj instanceof List){
            loadListRelation((List<?>) obj, path);
        } else {
            throw new RuntimeException("无法识别的类型!");
        }
    }
    /**
     * 解析List配置信息
     * @param obj
     * @param path
     */
    @SuppressWarnings("unchecked")
    private void loadListRelation(List<?> obj, String path) {
        if(obj.size() <= 0){
            return;
        }
        if(obj.get(0) instanceof String){
            relation.put(path, (List<String>) obj);
            return;
        }
        loadRelation(obj.get(0), path + "[]");
    }
    /**
     * 解析MAP配置信息
     * @param obj
     * @param path
     */
    private void loadMapRelation(Map<?, ?> obj, String path) {
        for(Object key : obj.keySet()){
            Object val = obj.get(key);
            if(val instanceof String){
                relation.put(path + space(path) + key.toString(), Lang.list(val.toString()));
                continue;
            }
            loadRelation(obj.get(key), path + space(path) + key.toString());
        }
    }
    
    private static String space(String path){
        return "".equals(path) ? "" : ".";
    }
    
    
}
