// print('hello world');

//1、包引用
var _ = require('lodash');
var process = require('process');

// print("now package path=" + __package__.libraryPaths());

// _.forEach(process.argv, function(n, i){
//     print("argv=" + n, "index=" + i);
// })

var arry1 = ['a' , 'b',  'c', 'd'];

_.forEach(arry1, function(n, i){
    // print("argv=" + n, "index=" + i);
});


// print('test debug');

//2、加密文件举例:topjs3 --compile ./test.jsc(加密生成文件) ./test.js(被加密文件) 


//3、console控制台输出
print('============console控制台输出=============');
var cl = require('console');
cl.log('测试: %s', '胡志辉');
cl.log('测试: %s', '胡志辉', 'huzhihui', 123);

cl.log('测试:%d', 123);  //结果:NaN
cl.log('测试:%d', 'abc');
cl.log('测试:%d', 123, 666, 'abc');

cl.log('测试:%f', 123.123);
cl.log('测试:%f', 123);
cl.log('测试:%f', 123.123, 123);

var info1 =  {};
info1.name = '胡志辉';
info1.age = 24;
cl.log(typeof '测试:%o', info1);

var info2 =  {'name':'hzh', 'age':24};
cl.log(typeof '测试:%j', info2);  //注意:%j是把对象解析成字符串

//占位符%c  google浏览器剩下
// cl.log("%c ", "background: url(http://pic44.nipic.com/20140723/19276212_171901262000_2.jpg)  no-repeat center;padding-left:800px;padding-bottom:600px;")

cl.log('-------------');

cl.info('huzhihui');

cl.info('测试:%s', 'huzhihui');

cl.info('测试:%d', '123' + 1231);

cl.info('测试:%f', 123.123);
cl.info('测试:%f', '123.123');

cl.info('测试:%o', {'name':'huzhihui'});

cl.info('测试:%j', {'name':'huzhihui'});
cl.info('=============');

cl.debug('it is a debug');
cl.warn('it is a warn');
cl.error('it is a error');

//assert断言
cl.assert(true, 'do nothing'); //true不输出任何信息
cl.assert(false, 'have %s', 'error');
cl.assert(false, 'have error');
cl.assert(false, '=============');

//4、events事件
print('============events事件=============');
var Events = require('events');
var os = require('os');
var evt = new Events;

//on绑定事件
evt.on('myevent', function(time, index){
    cl.log('now time:' + time + ' 索引:' +index);
})

// evt.emit('myevent', os.getNow()) //getNow获取操作系统时间

//疑问1:
// var process = require('process');
// process.mainLoop();  // 主循环事件的作用

//clearEvent
for(var i=1; i<10; i++){
    evt.emit('myevent', os.getNow(), i);
    if(i == 5){
        evt.clearEvent('myevent');
        break;
    }
}


//5、fs-文件系统
print('============fs-文件系统=============');
var fs = require('fs')
data = fs.openFile('C:/Projects/Topjs3API/fileTest.txt');
print(data);
cl.log(data);

// fs.openRawFile(); 打开二进制文件
// fs.chmod();  更改文件权限

//复制文件
//fs.copyFile('C:/Projects/Topjs3API/fileTest.txt', 'C:/Projects/Topjs3API/fileTest123.txt', false);

//判断文件或文件夹是否存在
print(fs.exists('C:/Projects/Topjs3API/fileTest.txt'));
print(fs.fileExists('C:/Projects/Topjs3API/fileTest.txt'));
print(fs.dirExists('C:/Projects/Topjs3API/fileTest.txt'));

//疑问2:写代码时如何快速显示api

//创建硬链接
print('创建硬链接:' + fs.link('C:/Projects/Topjs3API/fileDemo/a.txt', 'C:/Projects/Topjs3API/fileDemo/b.txt'));
//疑问3:创建出来的硬链接里面是啥??

print(fs.stat('C:/Projects/Topjs3API/fileTest.txt'));
cl.log(fs.stat('C:/Projects/Topjs3API/fileTest.txt'));
//FileStat 对象结构需要使用console.log打印
print('--------------');
print(fs.stat('C:/Projects/Topjs3API/'));
cl.log(fs.stat('C:/Projects/Topjs3API/'));
print('--------------');
print(fs.stat('C:/Projects/Topjs3API'));
cl.log(fs.stat('C:/Projects/Topjs3API'));  //文件夹加不加最后的斜杠都一样
print('--------------');

//mkdir创建文件夹
// fs.mkdir('C:/Projects/Topjs3API/fileDemo')

print('获取文件的绝对路径:' + fs.realpath('C:/Projects/Topjs3API/fileTest.txt'));

//rename重命名文件 或者 移动文件
print(fs.rename('C:/Projects/Topjs3API/fileTest123.txt', 'C:/Projects/Topjs3API/fileTest321.txt', true));

//rmdir移除文件夹
print(fs.rmdir('C:/Projects/Topjs3API/fileDemo', false));

//删除文件
// print(fs.unlink('C:/Projects/Topjs3API/fileDemo/b.txt'));

//listDir 获取文件夹下的文件信息列表
var filelist = fs.listDir('C:/Projects/Topjs3API/fileDemo');
var _ = require('lodash');
print(filelist.length);

//注意此处是从0开始
for(var i=0; i<filelist.length; i++){
    print(_.toString(filelist[i]));
    // print(filelist[i]);
};

///注意编码问题
data1 = fs.readFile('C:/Projects/Topjs3API/fileTest.txt', 'gbk');
print(data1);

fs.writeFile('C:/Projects/Topjs3API/fileTest321.txt', '哈哈哈哈哈哈哈哈哈');
data2 = fs.readFile('C:/Projects/Topjs3API/fileTest321.txt');
print(data2);
data2 = fs.readFile('C:/Projects/Topjs3API/fileTest321.txt', 'gbk');
print(data2);

//tmpdir获取操作系统的临时目录
print(fs.tmpdir());

//homedir获取操作系统当前用户的home目录
print(fs.homedir());

print('------TextFileStream类------');
//setCodec设置文件编码
file = fs.openFile('C:/Projects/Topjs3API/fileTest.txt', 'r');
print(file.codec()); //结果显示是System
file.setCodec('UTF-8');
//codec查看设置的文件编码
print(file.codec());

data3 = fs.readFile('C:/Projects/Topjs3API/fileTest.txt');
print(data3);
//设置文件编码和查看文件编码行为好像只能在打开文件的操作中进行
//疑问:设置文件编码会直接改写文件整体的编码格式吗??为什么设置了文件编码后再读取的时候不是按照之前设置的我那件编码来的?

//是否自动检测Unicode  
//疑问:有什么用?
file.setAutoDetectUnicode(true);
print(file.isAutoDetectUnicode());

//设置是否添加编码BOM
//疑问:编码BOM是什么?
file.setGenerateByteOrderMark(true);
print(file.isGenerateByteOrderMark());
//文档中方法名写错了

//setAutoFlush设置是否每次在写入文件时自动刷新缓存至文件
//isAutoFlush查看是否每次在写入文件时自动刷新缓存至文件

//atEnd()是否读取到文件结尾
print(file.atEnd());

//reset()将文件读取位置重置
print(file.reset());

// flush()刷新缓存至文件
file.flush();

// seek([iPos])寻找文件读取位置
print(file.seek(5));

// pos()获取当前文件读取位置
print(file.pos());

// skipWhiteSpace()设置自动忽略空格
file.skipWhiteSpace();

// readLine([iMaxLen])读取一行
print(file.readLine());

// readAll()读取全部文件内容
print(file.readAll());

// read([iMaxLen])读取指定大小文本块
print(file.read(2));

// write([iText])写入文件
var file = fs.openFile('C:/Projects/Topjs3API/fileTest.txt321', 'w')
//方式1:
/*
file.write('aaabbbccc');
// close()关闭文件句柄
file.close();
*/

// 方式2:
file.setAutoFlush(true);  //设置是否每次在写入文件时自动刷新缓存至文件
file.write('aaaaaaaaaaaaaa');
//如果没有跟方法2一样设置AuotFlush,则需要使用close()手动关闭才能保存写入的内容

// print('------RawFileStream类------\n');
//1、setAutoFlush([iAutoFlush])设置是否每次在写入文件时自动刷新缓存至文件
//2、isAutoFlush()是否每次在写入文件时自动刷新缓存至文件
//3、atEnd()是否读取到文件结尾
//4、reset()将文件读取位置重置
//5、flush()刷新缓存至文件
//6、seek([iPos])寻找文件读取位置
//7、pos()获取当前文件读取位置
//8、readAll()读取全部文件内容
//9、read([iMaxLen])读取指定大小文本块
//10、write([iText])写入文件
//11、close()关闭文件句柄

print('------os - 工具模块------\n');
var os = require('os');
print('操作系统位数:' + os.arch());
print('计算机主机名:' + os.hostname());

print('计算机网卡信息:' + os.networkInterfaces());
// cl.log('计算机网卡信息:' + os.networkInterfaces())

// networks = os.networkInterfaces();
// print(networks.length);
// for(var i=0; i<networks.length; i++){
//     cl.log(networks[i]);
// };

print('操作系统临时目录:' + os.tmpdir());
print('操作系统当前用户HOME目录:' + os.homedir());
print('操作系统类型:' + os.type());
print('操作系统内核类型:' + os.kernelType());
print('操作系统内核版本:' + os.kernelVersion());
print('操作系统版本:' + os.version());
print('获取操作系统名称:' + os.name());
print('获取操作系统名称2:' + os.prettyName());
print('获取操作系统时间:' + os.getNow());
print('获取操作系统日期:' + os.getToday());

print('\n');
// package - 包管理
print('------package - 包管理------');
//通过全局变量__package__可以获取到包管理对象;
print('查看当前包的路径列表:' + __package__.libraryPaths());
// 1、addLibraryPath(path)添加包目录;添加后的path会放到libraryPaths()的最前面;
// 2、setLibraryPaths(paths)重新设置包路径;
// 3、libraryPaths()获取当前的包目录列表;

print('\n');
print('------process - 进程------');
var process = require('process');
print('topjs执行文件路径:' + process.topjsBinPath());
print('当前进程的PID号:' + process.pid());
print('平台名称:' + process.platform());
print('当前执行的脚本文件路径(不包含文件名):' + process.evalFileDir());
print('当前执行的脚本文件名:' + process.evalFileName());
print('当前执行的脚本文件除去后缀后的名称:' + process.evalFileBaseName());

var event = process.createEvent();
cl.log(event);

// print('获取环境变量名:' + process.getEnv('path'));

//setEnv设置环境变量:process.setEnv('path','C:\topJs\topjs3\bin;');

//gc()立即对进程进行垃圾回收
// process.gc();

//exit()退出
// process.exit(0);
//疑问:exit中的数字代表啥?

// mainLoop()开始事件主循环
// process.mainLoop();

//exec执行外部命令
// cl.log(process.exec('dir', ['C:/Projects/Topjs3API']));
cl.log(process.exec('ipconfig'));

//argv返回运行时的命令行参数
// _.forEach(process.argv, function(n){
//     cl.log(n);
// })

// stdout标准输出流
var stdout = process.stdout;
// print(stdout);
stdout.setCodec('UTF-8');  //设置文件编码
print(stdout.codec())  //获取设置的文件编码
stdout.setAutoDetectUnicode(true);  //设置自动检测Unicode
print(stdout.isAutoDetectUnicode());  //是否自动检测Unicode
stdout.setAutoFlush(false);  //设置是否每次在写入文件时自动刷新缓存至文件
print(stdout.isAutoFlush());  //查看是否每次在写入文件时自动刷新缓存至文件
print(stdout.atEnd());  //是否读取到文件结尾
// stdout.reset();  //将文件读取位置重置 ---疑问:此处报错,原因未知
stdout.flush();  //刷新缓存至文件
print(stdout.readLine());  //读取一行
print(stdout.readAll());  //读取全部内容文件
print(stdout.read(1));  //读取指定大小文本块
stdout.write('aaaaaaaaa');  //写入文件
print(stdout);

// stdin标准输入流
var stdin = process.stdin;

// stderr标准错误流
var stderr = process.stderr;

print('\n');
print('------qt.widgets gui操作------');
/*
var QtCore = require('qt.core');
var QtGui = require('qt.gui');
var QtWidgets = require('qt.widgets');
//定义容器
var frame = new QtWidgets.QFrame();
//定义水平布局至容器
var layout = new QtWidgets.QHBoxLayout(frame);
//定义组件
var button1 = new QtWidgets.QPushButton('one');
var button2 = new QtWidgets.QPushButton('two');
var button3 = new QtWidgets.QPushButton('three');
var button4 = new QtWidgets.QPushButton('four');
var button5 = new QtWidgets.QPushButton('five');
//添加组件至布局
layout.addWidget(button1);
layout.addWidget(button2);
layout.addWidget(button3);
layout.addWidget(button4);
layout.addWidget(button5);
frame.show();
process.mainLoop();

//qt不能执行,报错:QWidget: Cannot create a QWidget without QApplication

*/

print('\n');
print('------Lodash介绍------');
//1、toString(obj)  将对象转为string;
var _ = require('lodash');
str1 = _.toString(null)
print(typeof str1);  //=>空字符串

str2 = _.toString(undefined)
print(typeof str2);  //=>空字符串

print(_.toString('abcd'));  //=>abcd
print(_.toString(true));  //=>true
print(_.toString(false));  //=>false
print(_.toString(0.01));  //=>0.01

str3 = _.toString({a:'aa'})
print(str3);  //=>{"a":"aa"} 注意:object或array等类型会返回JSON.stringify()字符串;
print(typeof str3);  //=>string

str4 = _.toString([0,'a',0.11])  ////=>[0,"aa",0.11] 注意:同上
print(str4);  //=>[0,"aa",0.11]
print(typeof str4);  //=>string

str5 = _.toString(function(){return 'abcdef';})
print(str5);  //=>function(){return 'abcdef';}
print(typeof str5);  //=>string 注意:如果里面是函数,那么结果也是string

//2、_.isEmpty(obj)  判断对象是否为空
//=>以下打印true
print(_.isEmpty(null));
print(_.isEmpty(undefined));
print(_.isEmpty(''));
print(_.isEmpty([]));
print(_.isEmpty({}));
//=>以下打印false
print(_.isEmpty(['a']));
print(_.isEmpty({a:1}));
print(_.isEmpty(false));
print(_.isEmpty(true));  //注意boolean也会返回true
print(_.isEmpty(0));
print(_.isEmpty('abc'));
print(_.isEmpty(0.1234));

//3、_.toNumber(obj)  对象转为数字;
var n = _.toNumber(undefined);
print(n);  //=>0  注意在topjs3中此处undefined是转为0
var n = _.toNumber('huzhihui');
print(n);  //=>NaN
var n = _.toNumber({'name':'huzhihui'});
print(n);  //=>NaN

//4、_.isValid(obj)  判断对象是否有效;
//=>以下打印false
print('null==>' + _.isValid(null));
print(_.isValid(undefined));
//=>以下打印true
print(_.isValid(true));
print(_.isValid(0));
print(_.isValid('abc'));
print(_.isValid(0.1234));
print(_.isValid(false));
print(_.isValid([]));
print(_.isValid({}));

//5、_.isTrue(obj)  判断对象是否为真;
//=>以下打印false
print('==>' + _.isTrue(null));
print(_.isTrue(undefined));
print(_.isTrue(''));
print(_.isTrue([]));
print(_.isTrue({}));
print(_.isTrue(false));
print(_.isTrue(0));
print(_.isTrue('0'));
//=>以下打印true
print(_.isTrue(['a']));
print(_.isTrue({a:1}));
print(_.isTrue(true));
print(_.isTrue(1));
print(_.isTrue('abc'));
print(_.isEmpty(0.1234));

//6、_.fuzzyEqual(value1, value2)  模糊比较两个数字是否相等,判断的公差为0.000001;
print('是否相等:' + _.fuzzyEqual(1, 1.00000000001));
//7、_.fuzzyLessThan(value1, value2)  模糊判断value1是否小于value2,判断的公差为0.000001;
print('是否小于:' + _.fuzzyEqual(1, 1.00000000001));
//8、_.fuzzyLessEqual(value1, value2)  模糊判断value1是否小于等于value2,判断的公差为0.000001;
print('是否小于等于:' + _.fuzzyEqual(1, 1.00000000001));
//9、_.fuzzyGreaterThan(value1, value2)  模糊判断value1是否大于value2,判断的公差为0.000001;
print('是否大于' + _.fuzzyEqual(1, 1.00000000001));
//10、_.fuzzyGreaterEqual(value1, value2)  模糊判断value1是否大于等于value2,判断的公差为0.000001;
print('是否大于等于:' + _.fuzzyEqual(1, 1.00000000001));

//11、_.format(template, replace1, replace2, …)  使用replace1、replace2、replace3…替换template中的占位符, 占位符为{number}
var template = "my {0} is {1}";
var res = _.format(template, "name", 'huzhihui');
print(res);


//12、_.formatUnicorn(template, kv)  使用kv中匹配的键的值替换模板中的占位符, 占位符为${string}
var template = "my name is ${name}, age is ${age}";
var res = _.formatUnicorn(template, {'name':'huzhihui', 'age':24});
print(res);

//13、_.romanize(num)  将数字转换成罗马数字
print(_.romanize(1));
print(_.romanize(2));
print(_.romanize(3));

//14、_.deromanize(str)  将罗马数字转换成数字
print(_.deromanize('III'));  //罗马数字是字符串格式

print('\n');
print('------mockjs - 随机数据------');
//mockjs - 生成随机数据,拦截 Ajax 请求
var Mock = require('mockjs');
// print(Mock.mock({"string|1-10": "*"}));
//此处会对对象中的value值进行范围内随机相加
print(_.toString(Mock.mock({"string|1-10": "*"}))); //=>{"string":"*********"}
print(_.toString(Mock.mock({"string|2": "*"})));
print(_.toString(Mock.mock({"number|+1": 100})));//此处的number值 是初始值,一般跟数组配合使用
print(_.toString(Mock.mock({"number|1-100": 10}))); //此处的number值只是用来确定类型

print(_.toString(Mock.mock({"number|1-100.1-10": 10})));
print(_.toString(Mock.mock({"number|123.1-10": 10})));
print(_.toString(Mock.mock({"number|123.2": 10})));//注意:若浮点数是个固定值,那么该固定值就代表小数点向后的小数的位数
print(_.toString(Mock.mock({"number|123.10": 10})));

//生成随机的布尔值,true和false的概率各是1/2
print(_.toString(Mock.mock({"boolean|1": true})));

a = [1, 2, 3, 4, 5, 6];
print(a.slice(4));