const electron = require('electron');
const log = require('electron-xlog');
const url = require('url');
const os = require('os');
const path = require('path');
const {execFile} = require('child_process');
//const uuid = require('uuid');
const querystring = require('querystring');
const { app, BrowserWindow, ipcMain, remote, Menu, crashReporter, clipboard } = require('electron');

//log.transports.console.format = '{text}';
//log.transports.file.level = 'info';
//log.transports.file.fileName = 'tclass.log';
log.transports.file.setPath(path.join((process.platform != 'darwin' ? process.env.USERPROFILE : process.env.HOME), 'TClass'), 'TClass')

const swin = require(path.join(__dirname, 'js', 'window.js'))
const ELKLog = require(path.join(__dirname, 'js', 'logreport.js'))
const axios = require('axios')
var startUrl = "";

const class_width = 1280;
const class_height = 750;

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.

// 定义全局变量
global.data = {
  uuid: process.platform + "_" + Math.floor(Math.random() * 10000),
  sdkAppId: 1400127140,   // 默认sdkappid(可变)
  userId: "",
  userToken: "",
  userSig: "",
  nickName: "",
  configUrl: "",
  guest: false,     // 是否游客
  env: "env",
  mode: "saas",
  minVer: 701,
  test: false,      // 是否测试模式
  classId: 0,
  classToken: '',   // 课堂密码
  classInfo: {}, // 课堂详情
  isClassEnter: false,
  token: "",
  ticKey: "",
  role: "",
  expire: 0,
  dlgId: 100,
  subvideo: false,  // 是否正在推辅路
  deviceTestId: 0,       // 设备测试窗口id
  mirror: true,    // 是否镜像
  beauty: false,    // 是否开启美颜
  speakerVolume: 0,   // 扬声器音量
  micVolume: 50,    // 麦克风音量
  sendMsg: true,    // 是否允许发送消息
  handupStu: [],     // 举手成员列表
  custom_datas: [],
  appName: "",
  appIconUrl: "",
  companyId: "",
  component: false,   // 是否组件
  class_hwnd: 0,
  is_checkin_ing:false,
  lastReportTime: 0,  // 上次心跳时间
  curQuestionId: 0,   // 当前答题卡id
  curTickCount: 0   // 当前问题计时
}

var ELKdata = {
  "action": "requesetMainReport", // 	事件名称
  "version": "", // 版本号
  "action_result": 0, // 事件错误码
  "action_info": "", // 	错误详细信息
  "userid": "", // 登录用户的id
  "time_consume": 0, //事件耗时，单位毫秒
  "sdkappid": "", // sdkappid
  "platform": process.platform, // 事件对应的平台
  "decice_id": global.data.uuid,
  "log_time": new Date(), //  时间上报时的本地秒级时间戳
  "business": 'saas', //  业务sdk名字
  "classid": "", // 房间id，进房以及在房间中的所有事件都要带上
  "extra_info": "", // 可扩展字段
  "net_type": 'unknown', //
  "mode": "",
  "role": "",
  "userAgent": null
}

//ELK上报数据头
let config = {
  headers: {
    "Content-type": "application/x-www-form-urlencoded"
  }
}

if (process.platform != 'darwin') {	// Mac 路径不同
  log.transports.console.format = '{h}:{i}:{s}.{ms} > {text}\t\t';
}

// 消息转发列表
const ipcMsgList = ['DEVICES:MIC', 'DEVICES:CAMERA', 'DEVICES:SPEAKER', 'DEVICES:CHANGE', 'DEVICES:QUERY', 'DEVICES:LIST',
  'SET:SPEAKERVOLUME', 'SET:MICVOLUME', 'SET:BEAUTY', 'SET:MIRROR', 'TOOL:SCREEN', 'TOOL:PLAYVIDEO', 'MEMBER:CLEARHANDUP',
  'IM:SENDTEXTMSG', 'IM:SENDCUSTOMMSG',
  'TRTC:Status', 'TRTC:Update', 'CLASS:OpenDoc', 'CTL:Status', 'CTL:Control', 'CTL:KickOff', 'CTL:Class', 'CTL:HandUp'];

// 单实例
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
  app.quit();
  return;
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    swin.activeTopWin();
  })
}

// 注册Chrome浏览器协议
const args = [];
if (!app.isPackaged) {
  args.push(path.resolve(process.argv[1]));
}
args.push('--');
const PROTOCOL = "tc-videochat";
// 在安装时注册，卸载时反注册
if (process.platform == 'darwin') {
  app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args);
}
handleArgv(process.argv);
app.on('second-instance', (event, argv) => {
  if (process.platform == "win32") { // Windows
    handleArgv(argv);
  }
});
app.on('open-url', (event, urlStr) => {
  handleUrl(urlStr);
});


// 关闭硬件加速
// app.disableHardwareAcceleration();

//消息传递
// 课堂列表窗口
ipcMain.on('WIN_CLASSLIST:OPEN', function (event, msg, data) {
  //swin.addWindow('WIN_CLASSLIST', 1280, 960, 'html/classlist.html', !global.data.guest, false, 0);
  swin.addWindow('WIN_CLASSLIST', '', 1280, 760, 'html/page_classlist.html', true, data);
  swin.closeWindow('WIN_LOGIN');
})

// 课堂窗口
ipcMain.on('WIN_CLASS:OPEN', function (event, msg, classid, data) {
  openLoadingWin();
  swin.closeWindow('WIN_LOGIN');
})

ipcMain.on('WIN_CLASSLIST:CLOSE', function (event, msg, classid, data) {
  swin.closeWindow('WIN_CLASSLIST');
})

ipcMain.on('WIN_CLASS:RELOAD', function (event, msg, classType, data) {
  log.info("[TAG-MAIN] reload->class type: " + classType);
  if (classType == 'public') {
    swin.reloadWindow('WIN_CLASS', 'html/page_classpublic.html', data);
  } else if (classType == '1v1') {
    swin.reloadWindow('WIN_CLASS', 'html/page_class1v1.html', data);
  } else {
    swin.reloadWindow('WIN_CLASS', 'html/page_class1vN.html', data);
  }

})


ipcMain.on('WIN_CLASS:ACTIVE', function (event, msg, classid, data) {
  var classWin = swin.findWindow('WIN_CLASS');
  if (typeof (classWin) != 'undefined') {
    classWin.webContents.send('join', data);
  }
})

ipcMain.on('WIN_LOGIN:OPEN', function (event, msg) {
  startNormal();
})

ipcMain.on('WIN_LOGIN:SET', function(event, msg){
  swin.reloadWindow('WIN_LOGIN', 'html/page_login_set.html', null);
})

ipcMain.on('WIN_LOGIN:BACK', function(event, msg){
  swin.goback('WIN_LOGIN');
})

ipcMain.on('WIN_CLASS:CLOSE', function (event, msg, classid) {
  swin.closeWindow('WIN_CLASS');
})

ipcMain.on('WIN_CLASS:SHOW', function (event, msg, isShow) {
  swin.showWindow('WIN_CLASS', isShow);
})

ipcMain.on('WIN_CLASS:FULLSCREEN', function (event, msg, classid) {
  swin.setWindowFullScreen('WIN_CLASS', true);
})

ipcMain.on('WIN_CLASS:NORMALSCREEN', function (event, msg, classid) {
  swin.setWindowFullScreen('WIN_CLASS', false);
})

// 展示注册对话框
ipcMain.on('WIN_REGIST:OPEN', function (event, msg, data) {
  swin.addWindow('WIN_REGIST', '', 300, 270, 'html/regist.html', true, data);
})

ipcMain.on('WIN_REGIST:CLOSE', function (event, msg, data) {
  swin.closeWindow('WIN_REGIST', false);
})

// 打开设备测试页
ipcMain.on('WIN_DEVICES:OPEN', function (event, msg, data) {
  deviceWin = swin.addWindow('WIN_DEVICES', 'WIN_CLASS', 800, 680, 'html/device.html', true, data);
  global.data.deviceTestId = deviceWin.id;
})

ipcMain.on('WIN_DEVICES:CLOSE', function (event, msg, data) {
  global.data.deviceTestId = 0;
  swin.closeWindow('WIN_DEVICES');
})

// 展示成员列表
ipcMain.on('WIN_MEMBER:OPEN', function (event, msg, data) {
  swin.addWindow('WIN_MEMBER', 'WIN_CLASS', 700, 470, 'html/classmem.html', true, data);
})

ipcMain.on('WIN_MEMBER:CLOSE', function (event, msg, data) {
  swin.closeWindow('WIN_MEMBER');
})

// 展示设置页
ipcMain.on('WIN_SET:OPEN', function (event, classId) {
  setWin = swin.addWindow('WIN_SET', 'WIN_CLASS', 913, 469, 'html/dlg_set.html', true, data);
  if (typeof (setWin) != 'undefined') {
    global.data.deviceTestId = setWin.id;
  }
})

ipcMain.on('WIN_SCREEN:OPEN', function (event, msg, sources) {
  swin.addWindow('WIN_SCREEN', '', 800, 600, 'html/screenSourceDlg.html', true, data);
})

ipcMain.on('WIN_SET:CLOSE', function (event, msg, data) {
  swin.closeWindow('WIN_SET');
  global.data.deviceTestId = 0;
})

// 展示工具页
ipcMain.on('WIN_TOOL:OPEN', function (event, classId, data) {
  setWin = swin.addWindow('WIN_TOOL', 'WIN_CLASS', 426, 195, 'html/tool.html', true, data);
})
ipcMain.on('WIN_TOOL:CLOSE', function (event, msg, data) {
  // 先将焦点给主页面(避免Window下焦点丢失)
  var classWin = swin.findWindow('WIN_CLASS');
  classWin.focus();
  swin.closeWindow('WIN_TOOL');
})

ipcMain.on('WIN_CHECKIN_DLG:CLOSE', function (event, msg, data) {
  // 先将焦点给主页面(避免Window下焦点丢失)
  var classWin = swin.findWindow('WIN_CLASS');
  classWin.focus();
  swin.closeWindow('WIN_CHECKIN_DLG');
})


// 展示签到本
ipcMain.on('WIN_CHECKIN_DLG:OPEN', function (event, classId, data) {
  setWin = swin.addWindow('WIN_CHECKIN_DLG', 'WIN_CLASS', 426, 195, 'html/check_in_dialog.html', true, data);
})

//修正成签到结果
ipcMain.on('WIN_CHECKIN_DLG:END', function (event, classId, data) {
  var winCheckIn = swin.findWindow('WIN_CHECKIN_DLG');
  var position = winCheckIn.getPosition();
  winCheckIn.setSize(600, 620, false);
  winCheckIn.setPosition(position[0], position[1]-212);
  // setWin = swin.addWindow('WIN_CHECKIN_DLG', 426, 195, 'html/check_in_dialog.html', true, true, data);
})



// 展示答题卡
ipcMain.on('WIN_QUESTION:OPEN', function (event, msg, data) {
  setWin = swin.addWindow('WIN_TOOL_QUESTION', 'WIN_CLASS', 560, 280, 'html/page_question.html', true, data);
})
ipcMain.on('WIN_QUESTION:CLOSE', function (event, msg, data) {
  swin.closeWindow('WIN_TOOL_QUESTION');
})

ipcMain.on('WIN_QUESTION:RESIZE', function (event, msg, height){
  var winQestion = swin.findWindow('WIN_TOOL_QUESTION');
  var position = winQestion.getPosition();
  winQestion.setSize(560, 280+height, false);
  winQestion.setPosition(position[0], position[1]-height/2);

})

// 转发消息
for (var i = 0; i < ipcMsgList.length; i++) {
  ipcMain.on(ipcMsgList[i], (e, msg, param1, param2, param3, param4) => {
    log.info("[TAG-MAIN] recv boardcast message: " + msg);
    swin.boardcastWinMsg(msg, param1, param2, param3, param4);
  })
}

// 展示课件库页
ipcMain.on('WIN_DOCLIST:OPEN', function (event, classId, data) {
  var docListWin = swin.findWindow('WIN_DOCLIST');
  if (null == docListWin) {
    swin.addWindow('WIN_DOCLIST', 'WIN_CLASS', 700, 470, 'html/classdoc.html', true, data);
  } else {
    swin.showWindow('WIN_DOCLIST', true);
  }
})

ipcMain.on('WIN_DOCLIST:SHOW', function (event, msg, isShow) {
  swin.showWindow('WIN_DOCLIST', isShow);
  if (!isShow) {
    var classWin = swin.findWindow('WIN_CLASS');
    classWin.webContents.send('resume', null);
  }
})

ipcMain.on('WIN_DOCLIST:UPLOAD', function (event, classId, data) {
  log.info("[TAG-MAIN] recv reload upload: " + data);
  swin.reloadWindow('WIN_DOCLIST', 'html/classdocupload.html', data);
})

// 关闭课件库页
ipcMain.on('WIN_DOCLIST:CLOSE', function (event, classId) {
  // 先将焦点给主页面(避免Window下焦点丢失)
  var classWin = swin.findWindow('WIN_CLASS');
  classWin.focus();
  swin.closeWindow('WIN_DOCLIST');
})

// 返回课件库页
ipcMain.on('WIN_DOCLIST:BACK', function (event, classId) {
  swin.goback('WIN_DOCLIST');
})

// 课件上传页
ipcMain.on('WIN_DOCUPLOAD:OPEN', function (event, msg, classId, trans) {
  swin.addWindow('WIN_DOCUPLOAD', 'WIN_CLASS', 500, 200, 'html/uploaddoc.html', true, trans);
})

// 关闭课件上传页
ipcMain.on('WIN_DOCUPLOAD:CLOSE', function (event, classId) {
  swin.closeWindow('WIN_DOCUPLOAD');
})


ipcMain.on('viewClass:OpenVideoLocal', function (event, classId, data) {
  swin.closeWindow('WIN_DOCLIST');
  //classWin.webContents.send('CLASS:videoPlay', data);
})

ipcMain.on('QUITAPP', function (event, msg) {
  swin.closeAllWindow();
})

ipcMain.on('MAIN:CHECK', function (event, data) {
  log.info("[TAG-MAIN] check window enter");
  if (!swin.checkStatus()) {
    log.info("[TAG-MAIN] check window status fail!");
    swin.closeAllWindow();
  }
})

ipcMain.on('MAIN:EXEC', function(event, msg, file){
  log.info("[TAG-MAIN] exec->file:"+file);
  if (process.platform != 'darwin'){
    var child = require('child_process').spawn(
      file,
      [],
      {
        cmd: null,
        env: null,
        detached: true,
        stdio: 'ignore',
        windowsVerbatimArguments: process.platform !== 'darwin'
      }
    )
    child.on("exit", (code)=>{
      log.error("[TAG-MAIN] exec->exit:"+code);
    })
    log.info("[TAG-MAIN] exec->file: "+file+" completed");
  }  
  //execFile(file, [], {timeout: 0}, (error, stdout, stderr)=>{
  //  if (error){
  //    log.error("[TAG-MAIN] exec->err:"+error);
  //  }
  //})
})

// Electron 会在初始化后并准备
// 创建浏览器窗口时，调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', () => {
  main(process.argv);
})

// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
  // 在 macOS 上，除非用户用 Cmd + Q 确定地退出，
  // 否则绝大部分应用及其菜单栏会保持激活。
  log.info("[TAG-MAIN] All Window closed");
  //if (process.platform !== 'darwin') {
  app.quit();
  //}
})

app.on('activate', () => {
  // 在macOS上，当单击dock图标并且没有其他窗口打开时，
  // 通常在应用程序中重新创建一个窗口。
  // if (enterWin === null) {
  //   createWindow()
  // }
  log.info("[TAG-MAIN] app activate ");
})

process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';

// 在这个文件中，你可以续写应用剩下主进程代码。
// 也可以拆分成几个文件，然后用 require 导入。


// 拦截日志并上报
log.hooks.push((msg, transport) => {
  if (transport !== log.transports.file) {
    return msg;
  }

  sendLogInMain(msg.data);
  return msg;
})


function handleArgv(argv) {
  const prefix = `${PROTOCOL}:`;
  const offset = app.isPackaged ? 1 : 2;
  const url = argv.find((arg, i) => i >= offset && arg.startsWith(prefix));
  if (url) handleUrl(url);
}

function handleUrl(urlStr) { // ${PROTOCOL}:?a=1&b=2
  startUrl = urlStr;
  sendLogInMain("[TAG-MAIN] hanlderURl " + urlStr);
}

// var request = require('request');
function sendLogInMain(logdata) {
  ELKdata.extra_info = logdata;
  axios.post('https://ilivelog.qcloud.com', ELKdata, config)
    .then((response) => {
      console.log(" [TAG-MAIN]  response: " + response);
    })
    .catch((error) => {
      // console.log(" [TAG-MAIN]  response error: "+ error+", msg: "+logdata);
    })
  // request.post({
  //   headers: {'content-type' : 'application/x-www-form-urlencoded'},
  //   url: 'https://ilivelog.qcloud.com',
  //   json: ELKdata
  // }, function(error, response, body){
  //   console.log("ELK response.body " + body);

  //   if(error !== null)
  //     console.log("ELK response.error " + error);
  // });
}

// 初始化窗口模块
function initWindow() {
  swin.init();
}

function initApplicationMenu() {
  // Create the Application's main menu
  var template = [{
    label: "Application",
    submenu: [
      { label: "About Application", selector: "orderFrontStandardAboutPanel:" },
      { type: "separator" },
      { label: "Quit", accelerator: "Command+Q", click: function () { app.quit(); } }
    ]
  }, {
    label: "Edit",
    submenu: [
      { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
      { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
      { type: "separator" },
      { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
      { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
      { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
      { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
    ]
  }
  ];

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}

function initCrashReport() {
  crashReporter.start({
    productName: 'tic',
    companyName: 'tencent',
    submitURL: 'https://cs.api.qcloud.com/post',
    uploadToServer: true
  })
}

// 正常启动
function startNormal() {
  log.info("[TAG-MAIN] startNormal->enter mode: " + global.data.mode);
  //if (global.data.mode == "saas") {
    swin.addWindow('WIN_LOGIN', '', 888, 500, 'html/page_login_saas.html', true, {});
  //} else {
  //  swin.addWindow('WIN_LOGIN', '', 1270, 768, 'html/page_login.html', true, {});
  //}
}

// 通过URL呼起
function startByUrl() {
  log.info("[TAG-MAIN] startByUrl->url: " + startUrl);
  var urlInfo = url.parse(startUrl);
  var paths = urlInfo.pathname.split('/');
  var params = querystring.parse(urlInfo.query);
  if (paths.length >= 3) {
    global.data.companyId = parseInt(paths[1]);
    global.data.classId = parseInt(paths[2]);
    global.data.classToken = params.class_token;
    global.data.userId = params.user_id;
    global.data.userToken = params.user_token;
    global.data.userSig = params.user_sig;
    global.data.component = true;
    //global.data.configUrl = params.config_url;
    log.info("[TAG-MAIN] startByUrl->companyId: " + global.data.companyId + ", classId: " + global.data.classId + ", userId: " + global.data.userId + ", userToken: " + global.data.userToken);
    log.info("[TAG-MAIN] startByUrl->userSig: " + global.data.userSig);
    log.info("[TAG-MAIN] startByUrl->configUrl: " + global.data.configUrl);
    log.info("[TAG-MAIN] startByUrl->classToken: " + global.data.classToken);
    openLoadingWin();
    return;
  }
}

// 通过参数呼起
function startByParams(argv) {
  log.info("[TAG-MAIN] startByParams->argv: " + argv.length);
  var pos = (argv[1] == '.' || argv.length > 10 ? 2 : 1);
  global.data.companyId = parseInt(argv[pos++]);
  global.data.classId = parseInt(argv[pos++]);
  global.data.userId = argv[pos++];
  global.data.userToken = argv[pos++];
  global.data.userSig = argv[pos++];
  global.data.configUrl = argv[pos++];
  global.data.component = true;
  log.info("[TAG-MAIN] startByParams->companyId: " + global.data.companyId + ", classId: " + global.data.classId + ", userId: " + global.data.userId + ", userToken: " + global.data.userToken);
  log.info("[TAG-MAIN] startByParams->userSig: " + global.data.userSig);
  log.info("[TAG-MAIN] startByParams->configUrl: " + global.data.configUrl);
  openLoadingWin();
  //app.quit();
}

function openLoadingWin() {
  //if (global.data.mode == 'saas' || true) {
    var classWin = swin.addWindow('WIN_CLASS', '', class_width, class_height, 'html/page_class.html', true, {});
    //classWin.webContents.openDevTools();
    var wndBuf = classWin.getNativeWindowHandle();
    global.data.class_hwnd = (os.endianness()=='LE') ? wndBuf.readInt32LE() : wndBuf.readInt32BE();
  //} else {
  //  openClassWin();
  //}
}

function openClassWin() {
  var classWin = swin.addWindow('WIN_CLASS', '', class_width, class_height, 'html/page_classroom.html', true, {});
  var wndBuf = classWin.getNativeWindowHandle();
  global.data.class_hwnd = (os.endianness()=='LE') ? wndBuf.readInt32LE() : wndBuf.readInt32BE();
}

function main(argv) {
  log.info("[TAG-MAIN] main->argv: " + argv);
  initCrashReport();
  initWindow();
  initApplicationMenu();
  var package = require('./package.json');
  ELKdata.version = package.version+'.'+global.data.minVer;

  if (startUrl.length > 0) {
    startByUrl();
  } else if (argv.length > 4) {
    startByParams(argv);
  } else {
    // 先读剪切板
    var text = clipboard.readText();
    //log.info("[TAG-MAIN] main->clipboard: " + text);
    if (text.startsWith('tc-videochat://')) {
      startUrl = text;
      startByUrl();
    } else {
      startNormal();
    }
  }
}
