require('test');
function trim(text) {
    if(String.prototype.trim && !String.prototype.trim.call("\uFEFF\xA0")) {
        return text == null ? "" : String.prototype.trim.call(text);
    } else {
        var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
        return text == null ? "" : ( text + "" ).replace(rtrim, "");
    }
}
function compress(text) {
    return trim(text.replace(/[ \n\v\f\r\t]+/g, " ") .replace(/<!--.*?-->/g, ''));
}
function isEChar(c) {
    return /\s/.test(c);
}
//要点，当前位置的右边字符是当前指向字符，截取从左边字符开始算起
var compile = function(code) {
    var tokens = [];
    var codeLength = code.length,forwardChar = '',begin = 0,forward = 0,
        boundChar = '%',leftBound = '{',rightBound = '}',func = '',
        command =global.command = {cond:1, str:1, echo:1, getv:1, code:1, for:0, foreach:0, if:3, elseif:3, else:3, html:0, block:0, head:0, body:0, phpend:0};

    while(forward < codeLength) {//不断吃进字符
        forwardChar = code.charAt(forward);
        if(forwardChar==leftBound) {//左边界
            forwardChar = code.charAt(++forward);//前进一个字符
            if(forwardChar == boundChar) {
                tokens.push({fn:'echo', begin:begin, forward:forward-1, nodeType:0});
                begin = forward + 1;
                while(forwardChar=code.charAt(++forward)) {//这个循环寻找命令边界，找到结束，进行下一轮的正常扫描
                    if((isEChar(forwardChar) && trim(code.substring(begin, forward))!='')
                        || (forwardChar==leftBound && code.charAt(forward+1)==boundChar)
                        || (forwardChar==boundChar && code.charAt(forward+1)==rightBound)) {
                        func = trim(code.substring(begin, forward));
                        if(command[func]==undefined||func=='') {
                            throw new Error(func+' not exists');
                            break;//抛出异常，函数不存在
                        }

                        tokens.push({fn:func, begin:begin, forward:forward, nodeType:1});
                        //headerNode.cm = {fn:func, begin:begin, forward:forward+1};
                        begin = forward;
                        forward--;//因为总循环forward要加1
                        break;
                    }
                }
            }//{%getv aa aa a%}
        } else if(forwardChar == rightBound) {//右边界
            forwardChar = code.charAt(forward-1);
            if(forwardChar==boundChar) {//碰到结束边界出栈一个开始边界{{}}
                var rightBoundBefore = {fn:'echo', begin:begin, forward:forward-1, nodeType:0};
                tokens.push(rightBoundBefore);
                var currentNode = null,
                    lastNode = null;

                while(currentNode = tokens.pop()) {
                    if(currentNode.nodeType == 1) {
                        currentNode.tp = lastNode;
                        break;
                    } else {
                        currentNode.hp = lastNode;
                        lastNode = currentNode;
                    }
                }

                if(currentNode == null) throw new Error('open match error');
                currentNode.nodeType = 2;

                if(command[currentNode.fn]==1) {
                    console.log(currentNode.fn)
                    rightBoundBefore.fn = 'str';
                }
                tokens.push(currentNode);

                begin = forward + 1;
            }
        }
        forward++;
    }

    tokens.push({fn:'echo', begin:begin, forward:forward, nodeType:0});
    return tokens;
}
global.replaces = ['$out="";', '$out.=', ";\n", '$out'];
var fs = require('fs');
fs.readFile('tmp.txt', 'utf8', function (err, data) {
    if (err) throw err;
    code = "{%block " + data + "%}";
    var tokens = compile(code); //return;
    console.log(Set.obj2str(tokens));
    var t = tokens[1];


    fs.writeFile('message.html', traversal(t), function (err) {
        if (err) throw err;
        console.log('It\'s saved!'); //文件被保存
    });
});
/*code = "{%echo eee %}";
console.log(traversal(compile(code)[1]));*/
//compile('{%echo eee %}');
function traversal(gl) {
    if(!gl) return '';
    return parseCmd(gl, traversal(gl.tp)) + traversal(gl.hp);
}

/*function parseCmd(gl, tpl) {
    //console.log(gl.nodeType + gl.fn);
    switch (gl.fn) {
        case 'str':
            tpl = code.substring(gl.begin, gl.forward) ;//+ tpl
            break;
        case 'cmdblock':
            tpl = code.substring(gl.begin, gl.forward) + tpl ;+ tpl
            break;
        case 'phpend':
            tpl = tpl + "?>" ;+ tpl
            break;
        case 'getv':
            tpl = "<?php echo " + tpl + "?>";
            break;
        case 'echo':
            tpl = code.substring(gl.begin, gl.forward) ;
            break;
        case 'for':
            tpl = "<?php for" + tpl + "<?php } ?>";
            break;
        case 'cond':
            tpl = "(" + tpl +") { ?>";
            break;
        case 'if':
            tpl = "<?php if" + tpl + "<?php } ";
            if(end(gl)) tpl += '?>';
            break;
        case 'elseif':
            tpl = "else if" + tpl + "<?php } ";
            if(end(gl)) tpl += '?>';
            break;
        case 'else':
            tpl = "else" + tpl + "<?php } ";
            if(end(gl)) tpl += '?>';
            break;
        case 'url': break;
        case 'script':
            tpl = "<script>" + tpl + "</script>" ;
            break;
        case 'body':
            tpl = "<body>" + tpl + "</body>" ;
            break;
        case 'head':
            tpl = "<head>" + tpl + "</head>" ;
            break;
        case 'html':
            tpl = "<html>" + tpl + "</html>" ;
            break;
        case 'block':
            break;
        case 'code':
            tpl = "<?php" + tpl + "?>";
            break;
        default : break;
    }

    return tpl;
}*/


function parseCmd(gl, tpl) {
    switch (gl.fn) {
        case 'str':
            tpl = compress(code.substring(gl.begin, gl.forward));
            break;
        case 'phpopen':
            tpl = tpl + "<?php\n" ;+ tpl
            break;
        case 'getv':
            tpl = replaces[1] + tpl + replaces[2];
            break;
        case 'echo':
            if(trim(code.substring(gl.begin, gl.forward))=='') tpl = '';
            else
            tpl = replaces[1] + stringify(compress(code.substring(gl.begin, gl.forward))) + replaces[2];
            break;
        case 'for':
            tpl = "for" + tpl + "}";
            break;
        case 'cond':
            tpl = "(" + tpl +") {";
            break;
        case 'if':
            tpl = "if" + tpl + "}";
            break;
        case 'elseif':
            tpl = "else if" + tpl + "} ";
            break;
        case 'else':
            tpl = "else" + tpl + "} ";
            break;
        case 'url': break;
        case 'script':
            tpl = replaces[1] + stringify("<script>") + replaces[2] + tpl + replaces[1] + stringify("</script>") + replaces[2];
            break;
        case 'body':
            tpl = replaces[1] + stringify("<body>") + replaces[2] + tpl +  replaces[1] + stringify("</body>") + replaces[2];
            break;
        case 'head':
            tpl = replaces[1] + stringify("<head>") + replaces[2] + tpl + replaces[1] +stringify("</head>") + replaces[2];
            break;
        case 'html':
            tpl = replaces[1] + stringify("<html>") + replaces[2] + tpl + replaces[1] + stringify("</html>") + replaces[2];
            break;
        case 'block':
            break;
        case 'code':
            break;
        default : break;
    }

    return tpl;
}

function end(gl) {
    var end = true;
    while(gl = gl.hp) {
        if(command[gl.fn] == 3) {
            end = false;
        }
    }
    return end;
}

function stringify (code) {
    return '"' + code
        // 单引号与反斜杠转义
        .replace(/("|\\)/g, '\\$1')
        // 换行符转义(windows + linux)
        .replace(/\r/g, '\\r')
        .replace(/\n/g, '\\n') + '"';
};



/*
return lll
{%for
    {%str 222%}
    {%echo 222%}
    {%str 222%}
    dddd
%}

遍历到实体节点

* 收集资源表，依赖的资源：构建广义表，化为局部分析
* js底端优化
* require css
*
* 收集资源位置信息，做简单的匹配校验，建立数据结构，把数据结构交给后面的资源管理程序，任意的资源依赖注入，做到模块的灵活化
*
*
* html 渲染模块化


模块管理命令
程序扩展命令
资源路径的收集
* */

