
/*=============================================================================================
    author:ZhaoJun
    version:1.2
    email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
    'use strict';
/*-------------------------------------------------------------------------------------------*/
    
const fs=require("fs");
const path=require("path");


// 复用操作
/*-------------------------------------------------------------------------------------------*/	
    class online
    {
        static compile(df,del,zip,indexacc='/index.html')
        {
            var str,obj,df_,dfRoute
            df=df.replace(/\\/g,'/');
            df_=df+indexacc;
            dfRoute=df+'/route.js';


            $Load.clearn(df);
            obj=require(dfRoute)
            if(!obj.$root)obj.$root=''
            online.route(obj,dfRoute,obj.$root)


            function check(df)
            {
                var statInfo = fs.statSync(df);
                if(statInfo)
                {
                    if(statInfo.isDirectory())
                    {
                        var st1=fs.readdirSync(df);
                        if(st1)
                        {
                            for (let x of st1) 
                            {
                                x= df.concat('/').concat(x);
                                check(x);
                            }
                        }
                    }
                    else if(statInfo.isFile())
                    {
                        if(del)
                        {
                            if(path.extname(df)=='.online')
                            {
                                fs.unlinkSync(df);
                            }
                        }
                        else if(zip)
                        {
                            if(path.extname(df)=='._zip_')
                            {
                                fs.unlinkSync(df);
                            }
                        }
                        else if(path.extname(df)=='.html')
                        {
                            str=fs.readFileSync(df,{encoding:'utf8'})
                            fs.writeFileSync(df+'.online',online.parse(str,df==df_,obj.$root))
                        }
                    }
                }
            }
            check(df)
            if(del)
            {
                console.info('[打包应用]','删除打包完成');
            }
            else if(zip)
            {
                console.info('[打包应用]','删除压缩完成');
            }
            else
            {
                console.info('[打包应用]','编译完成');	
            }
        }

        static route(route,df,root)
        {
            function back(route)
            {
                let result=[]
                for (const key in route) 
                {
                    if(key=='$path' && Array.isArray(route[key]))
                    {
                        for (const iterator of route[key]) 
                        {
                            if(iterator.url)result.push(root+iterator.url)    
                        }
                    }
                    else if(key.indexOf('$')==-1)
                    {
                        result=result.concat(back(route[key]))
                    }
                }
                return result
            }

            function gen(arr)
            {
                arr=new Set(arr)
                //缓存文件存放的地方
                if(!route.$content)route.$content={}
                //不用缓存的文件
                if(!route.$actual)route.$actual=[]
                for (const key in route.$actual) 
                {
                    route.$actual[key]=root+route.$actual[key]
                }

                for (const iterator of arr) 
                {
                    let fx=fs.readFileSync('.'+iterator,{encoding:'utf8'});
                    if(!route.$actual.includes(iterator)) route.$content[iterator]=escape(online.parse(fx,undefined,root))
                }

                route.$root=$Config.web===undefined?route.$root:$Config.web
                let _str='$Route.load('+JSON.stringify(route,null,4)+')';
                fs.writeFileSync(df+'.online',_str)
            }

            gen(back(route))
        }

        static parse(str,tag,root)
        {
            var _str='';
            var __str='';
            var statInfo;
            if(!root)root='';
            if((typeof str) != 'string')
            {
                console.info('[打包应用]编译文件，必须为字符串',str);
                return '';
            }		
            var preg=/{{(.*?)=(.*?)}}/g
            var resu
            __str=str;
            try 
            {
                //为入口文件，解析script，link节点节点
                if(tag)
                {
                    //用于循环原生js引用,不可以引用外网
                    preg=/<script.*?src=([\"|\'])(.*?)\1.*?><\/script>/g
                    let pregRoute=/.*?route=([\"|\'])true\1/
                    while(resu=preg.exec(__str))
                    {
                        try 
                        {
                            statInfo = fs.statSync('.'+resu[2]);
                        } 
                        catch (error) 
                        {
                            continue;
                        }
                        if(statInfo.isFile())
                        {
                            if(pregRoute.test(resu[0])) _str=fs.readFileSync('.'+resu[2]+'.online',{encoding:'utf8'});
                            else _str=fs.readFileSync('.'+resu[2],{encoding:'utf8'});

                            _str=_str.replace('$M.online=false;','$M.online=true;');
                            str=str.replace(resu[0],'<script>\r\n'+_str+'\r\n</script>\r\n')
                        }
                    }


                    //用于循环原生css引用,不可以引用外网
                    preg=/<link.*?href=([\"|\'])(.*?)\1.*?><\/link>/g
                    while(resu=preg.exec(__str))
                    {
                        try 
                        {
                            statInfo = fs.statSync('.'+resu[2]);
                        } 
                        catch (error) 
                        {
                            continue;
                        }
                        
                        if(statInfo.isFile())
                        {
                            _str=fs.readFileSync('.'+resu[2],{encoding:'utf8'});
                            str=str.replace(resu[0],'<style>\r\n'+_str+'\r\n</style>\r\n')
                        }
                    }    
                }
                else
                {
                    //用于循环js,css,不可以引用外网
                    while(resu=preg.exec(__str))
                    {
                        statInfo = fs.statSync('.'+root+resu[2]);
                        if(statInfo.isFile())
                        {
                            switch (resu[1]) 
                            {
                                case 'css':
                                    _str=fs.readFileSync('.'+root+resu[2],{encoding:'utf8'});
                                    str=str.replace(resu[0],'<style>'+_str+'<\/style>\r\n')
                                break;
                                case 'js':
                                    _str=fs.readFileSync('.'+root+resu[2],{encoding:'utf8'});
                                    str=str.replace(resu[0],'<script>'+_str+'<\/script>\r\n')
                                break;
                            }
                        }
                    }
                    str=online.css(str)
                    str=online.id(str)
                    preg.lastIndex=0;
                    //用于异步循环页面,不可以引用外网
                    while(resu=preg.exec(__str))
                    {
                        statInfo = fs.statSync('.'+root+resu[2]);
                        if(statInfo.isFile())
                        {
                            switch (resu[1]) 
                            {
                                case 'page':
                                    _str=fs.readFileSync('.'+root+resu[2],{encoding:'utf8'});
                                    str=str.replace(resu[0],online.parse(_str,undefined,root))
                                break;
                            }
                        }
                    }
                } 

     
                
    
                return str; 	 
            } 
            catch (error) 
            {
                console.error('[打包应用]执行文件编译出错',error)
                return '';
            }
        }

        static random()
        {
            return (new Date()).getTime().toString().slice(6)+(Math.random().toString().slice(2))
        }
        
        static id (str)
        {
            if(!str)
            {
                return '';
            }
            var rega=/(<.*?\sid=)([\"|\'])(.*?)(\2.*?>)/g;
            var resa;
            var _rand=online.random();
            var _str=str;
            var _rando=''
            //找出数据中的id
            while (resa=rega.exec(_str)) 
            {
                if(resa[3] && resa[3].indexOf('_hash_')==-1)
                {
                    _rando=resa[3]+'_hash_'+_rand;
                    str=str.replace((new RegExp('([\\"|\\\'|\\s|\\,]{1}#)'+resa[3]+'\\b','g')),'$1'+_rando);//更改其他地方的此id
                    str=str.replace((new RegExp('for=([\\"|\\\'])'+resa[3]+'(\\1)','g')),'for=$1'+_rando+'$2');//更改其他地方的此id
                    str=str.replace((new RegExp('data\\-route\\-id=([\\"|\\\'])#'+resa[3]+'(\\1)','g')),'data-route-id=$1#'+_rando+'$2');//更改其他地方的此id
                    str=str.replace(resa[0],resa[1]+resa[2]+_rando+resa[4]);//更改标签里的id
                }
            }
            //str+=`<script>$Route.hash="_hash_${_rand}"</script>`
            return str;
        }
        
        static css (str,css)
        {
            if(!css)
            {
                css='';
            }
            var rega=/<style.*?>([\s|\S]*?)<\/style>/g;
            var resa;
            css+='\r\n\r\n';
            //找出数据中的style样式
            while (resa=rega.exec(str)) 
            {
                css+=(resa[1]+'\r\n\r\n');
            }
        
            var rand=online.random();
            var reg=/\.([^\d]*?)([,|\)|\[|\s|\{|\:|\b]{1})/g
            var res=''
            var _res=''
            
            //解析css样式
            while (res=reg.exec(css)) 
            {
                if(res[1] && res[1].indexOf('_hash_')==-1  && res[1].indexOf(';')==-1 && res[1].indexOf(':')==-1)
                {
                    _res=res[1]+'_hash_'+rand;
                    str=str.replace((new RegExp('class=([\\"|\\\'])([^=]*?\\b)'+res[1]+'(\\b.*?\\1)','g')),'class=$1$2'+_res+'$3');//更改其他地方样式
                    str=str.replace(res[0],'.'+_res+res[2]);//更改style
                }
            }
            return str;
        }	
    }
/*-------------------------------------------------------------------------------------------*/    
module.exports=online;