const {app, BrowserWindow} = require('electron');
const Config = require('electron-config')
const path = require('path')
// 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.
let win

function createWindow (appArgs) {
	
	// Create the browser window.
	var pref = {show:false, width: 1024, height: 768, title:"GeoGebra",webPreferences:{nodeIntegration:false, preload: __dirname + '/preload.js'}};
	const config = new Config();
	Object.assign(pref, config.get('winBounds'))
	win = new BrowserWindow(pref);
	win.setMenuBarVisibility(false);
	win.setAutoHideMenuBar(true);
	// and load the index.html of the app.
	var startUrl = `file://html/index.html`;
	if(appArgs && appArgs['perspective']){
		startUrl += "?perspective="+appArgs['perspective'];
	}
	if(appArgs && appArgs['prerelease']){
		startUrl += "&prerelease="+appArgs['prerelease'];
	}
	win.loadURL(startUrl);

	// Open the DevTools.
	// win.webContents.openDevTools()
	win.webContents.on('did-finish-load', () => {
		pref.show = true;
		win.show();
	});
	// Emitted when the window is closed.
	win.on('closed', () => {		
		console.log("closed");
		// Dereference the window object, usually you would store windows
		// in an array if your app supports multi windows, this is the time
		// when you should delete the corresponding element.
		win = null
	})
	win.unsaved = null;
	win.on('close', (e) => {
		if(!win.unsaved || !win.unsaved[0]){
				config.set('winBounds', win.getBounds());
				return;
		}		
		e.preventDefault();
		console.log("close killed");
			// Dereference the window object, usually you would store windows
			// in an array if your app supports multi windows, this is the time
			// when you should delete the corresponding element.
		const {dialog} = require('electron');
		
		dialog.showMessageBox(win,{message:win.unsaved[0],buttons:win.unsaved.slice(1)},function(e){
			if(e==0){
					win.loadURL("javascript:ggbApplet.checkSaved()");
			}
			if(e==1){
				win.unsaved = false;
				setTimeout(function(){	win.close();},100);
				}
			});
			
	});
	
}
function trySpawn(exec, params, callback){
	callback = callback || function(){};
	var spawn2 = require("child_process");
	const fs = require('fs');
	fs.access(exec, (err)=>	{err ? console.log(err) : callback(spawn2.spawn(exec, params)) });
}

function createShortcuts(locations){
	var cmdArgs = ["--createShortcut=GeoGebra.exe","-l="+locations.join()];
	trySpawn(process.execPath+"/../../Update.exe", cmdArgs,	function(proc){
				proc && proc.on('close', function(){
					console.log("Shortcuts added.\n");
					process.exit(0);
				});
			});
}

const environmentVariableAliases = {
  'HOME': 'home',
  'USERPROFILE': 'home',
  'APPDATA': 'appData',
  'TEMP': 'temp',
  'TMPDIR': 'temp'
};

function getPath(key) {
 
  let aliasKey = null;
  if (environmentVariableAliases[key]) {
    aliasKey = environmentVariableAliases[key];
  }

  let result = null;

  if (app) {
    try {
      result = app.getPath(aliasKey || key);
    } catch (e) {
      // NB: We'd like to log this but this method gets called too early
      //logger.debug(`Failed to get path for key, this may be expected: ${aliasKey || key}`);
    }
  }

  result = result || process.env[key];
  if (!result) {
    // NB: Try to fix up the most commonly fucked environment variables
    if (key.toLowerCase() === 'appdata' && process.env.USERPROFILE) {
      result = path.join(process.env.USERPROFILE, 'AppData', 'Roaming');
    }

    if (key.toLowerCase() === 'localappdata' && process.env.USERPROFILE) {
      result = path.join(process.env.USERPROFILE, 'AppData', 'Local');
    }
  }

  return result;
}

function p(strings, ...values) {
  let newVals = values.map((x) => getPath(x) || x);
  let newPath = String.raw(strings, ...newVals);
  let parts = newPath.split(/[\\\/]/).map((x) => x || '/');

  // Handle Windows edge case: If the execution host is cmd.exe, path.resolve() will not understand
  // what `C:` is (it needs to be `C:\`)
  if (process.platform === 'win32' && /:$/.test(parts[0])) parts[0] += '\\';

  try {
    return path.resolve(...parts);
  } catch (e) {
    return path.join(...parts);
  }
}

function updateShortcuts(){
	let locations = [];
	console.log("Shortcuts update started.");
	const fs = require('fs');
	let startupShortcut = p`${'appData'}/Microsoft/Windows/Start Menu/Programs/Startup/GeoGebra.lnk`;
	let hasStartupShortcut = fs.statSyncNoException(startupShortcut);
					
	let startMenuShortcut = p`${'appData'}/Microsoft/Windows/Start Menu/Programs/GeoGebra/GeoGebra.lnk`;
	let hasStartMenuShortcut = fs.statSyncNoException(startMenuShortcut);

	let desktopShortcut = p`${'userDesktop'}/GeoGebra.lnk`;
	let hasDesktopShortcut = fs.statSyncNoException(desktopShortcut);
					
	if (hasStartupShortcut){ 						
		locations.push('Startup');
	}
	if (hasStartMenuShortcut){ 						
		locations.push('StartMenu');
	}
	if (hasDesktopShortcut){
		locations.push('Desktop');
	}

	console.log("Desktop:" + desktopShortcut + " : "+!!hasDesktopShortcut);
	console.log("Start Menu:" + startMenuShortcut + " : "+!!hasStartMenuShortcut);
  
	if(locations){
		createShortcuts(locations);
	}
					
	console.log("Shortcuts update done.");
}
function onReady(){
	var nogui = false;
	var appArgs = {};
	process.argv.forEach(function (val, index, array) {
		console.log(val);
		if(val.match(/^--app=/)){
			appArgs['perspective']= val.match(/^--app=(.*)/)[1];
			if(appArgs['perspective'] === "whiteboard"){
				appArgs['prerelease'] = true;
			}
		}
			if(val.match(/^--squirrel/) && !val.match(/^--squirrel-firstrun/)){
				nogui = true;
				if(val.match(/^--squirrel-install/)){
					 createShortcuts(["Desktop","StartMenu"]);
					 console.log("Icon creation");
					
				}
				else if(val.match(/^--squirrel-update/)){
					 updateShortcuts();
					
				} else {
					// --squirrel-obsolete, ...
					process.exit(0);
				}
				
				return;
			}
		});
	if(nogui){
		console.log("No GUI, exiting");
		return;
	}
	app.setAppUserModelId("com.squirrel.geogebra.GeoGebra");
	let {protocol} = require('electron')
			 //protocol.registerStandardSchemes(['ggb'])
	protocol.unregisterProtocol('file', () => {})
	function localProtocol(request, callback) {
		const url = request.url.substr(5, request.url.length-5);
		if(url.match(/GGB_EXAM_ON/i)){
			trySpawn("disablekeys.exe",[],(proc)=>{global.disablekeys = proc});
			if(process.platform === 'darwin'){
				win.setKiosk(true);
			}
			return;
		}
		if(url.match(/GGB_EXAM_OFF/i)){
			if(process.platform === 'darwin'){
				win.setKiosk(false);
			}
			if(global.disablekeys){
				global.disablekeys.kill();
			}
		}
		if(url.match(/SETUNSAVED/i) ){
			var messagesJSON = decodeURIComponent(url.substring(url.indexOf("=")+1));
			win.unsaved= JSON.parse(messagesJSON);
			return;
		}
		console.log(request.url.length)
		const bits = url.split("?");
		const urlPath = bits[0];
		const normalized = path.normalize(`${__dirname}/${urlPath}`);
		callback({path: normalized });
		console.log(url);
		console.log({path: normalized});
	}

	function localError(error){
		if (error){
			 console.error('Failed to register protocol')
		}
		else {
			console.log('Registered protocol succesfully');
		}
	};

	protocol.registerFileProtocol('file', localProtocol, localError);	
	protocol.registerFileProtocol('app', localProtocol, localError);
	createWindow(appArgs);
	if(/^win/.test(process.platform)){
	 trySpawn("../Update.exe", ["--update", "https://download.geogebra.org/installers/6.0/"]);
	}else{
		console.log("No autoupdate for "+process.platform);
	}

}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', onReady)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
	console.log("allwindow");
	// On macOS it is common for applications and their menu bar
	// to stay active until the user quits explicitly with Cmd + Q
	if (process.platform !== 'darwin') {
		app.quit()
	}
})

app.on('activate', () => {
	console.log("activate");
	// On macOS it's common to re-create a window in the app when the
	// dock icon is clicked and there are no other windows open.
	if (win === null) {
		createWindow({})
	}
})
