// Modules to control application life and create native browser window
import { app, Menu, BrowserWindow, screen, ipcMain, shell, protocol, dialog, session } from 'electron';
import * as path from 'path';
import * as url from 'url';
import * as childProcess from 'child_process';
import * as fs from 'fs-extra';
import { openOrFocus } from './open-or-focus-app';

const pkStorageFolderName: string = "PK_storage";

// this should be placed at top of main.js to handle setup events quickly
if (handleSquirrelEvent()) {
  // squirrel event handled and app will exit in 1000ms, so don't do anything else
}
function handleSquirrelEvent(): boolean {
  if (process.argv.length === 1) {
    return false;
  }

  const appFolder = path.resolve(process.execPath, '..');
  const rootAtomFolder = path.resolve(appFolder, '..');
  const updateDotExe = path.resolve(path.join(rootAtomFolder, 'Update.exe'));
  const exeName = path.basename(process.execPath);

  const spawn = function (command, args) {
    let spawnedProcess, error;

    try {
      spawnedProcess = childProcess.spawn(command, args, { detached: true });
    } catch (error) { }

    return spawnedProcess;
  };

  const spawnUpdate = function (args) {
    return spawn(updateDotExe, args);
  };

  const squirrelEvent = process.argv[1];
  switch (squirrelEvent) {
    case '--squirrel-install':
    case '--squirrel-updated':
      // Optionally do things such as:
      // - Add your .exe to the PATH
      // - Write to the registry for things like file associations and
      //   explorer context menus

      // Install desktop and start menu shortcuts
      spawnUpdate(['--createShortcut', exeName]);

      setTimeout(app.quit, 1000);
      return true;

    case '--squirrel-uninstall':
      // Undo anything you did in the --squirrel-install and
      // --squirrel-updated handlers

      // Remove desktop and start menu shortcuts
      spawnUpdate(['--removeShortcut', exeName]);

      setTimeout(app.quit, 1000);
      return true;

    case '--squirrel-obsolete':
      // This is called on the outgoing version of your app before
      // we update to the new version - it's the opposite of
      // --squirrel-updated

      app.quit();
      return true;
  }
};

// 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 mainWindow;
let childWindow;
let quicknotewindow;

function createWindow() {

  const electronScreen = screen;
  const size = electronScreen.getPrimaryDisplay().workAreaSize;

  mainWindow = new BrowserWindow({
    x: 0, y: 0, width: size.width,
    height: size.height, parent: mainWindow,
    icon: path.join(__dirname, 'assets', 'icon', 'win_icon.ico'),
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      sandbox: false
    }
  });

  // and load the index.html of the app.
  //mainWindow.loadFile('build/index.html')

  // Load a URL in the window to the local index.html path
  const urlFormat = {
    pathname: path.join(__dirname, 'build/index.html'),
    protocol: 'file:',
    slashes: true
  }
  mainWindow.loadURL(url.format(urlFormat));

  protocol.registerHttpProtocol('loehnapplication', function (request) {
    if (childWindow) {

      if (request.url.indexOf('loehnapplication://auth365') !== -1) {
        mainWindow.webContents.send('officeauth', { msg: request.url });
        childWindow.close();
      } else {
        childWindow.close();
        mainWindow.loadURL(url.format(urlFormat));
      }

      childWindow = null;
    }
  });

  // Open the DevTools.
  //mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // 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.
    mainWindow = null;
  });



  let template: Electron.MenuItemConstructorOptions[] = [
    {
      label: 'Edit',
      submenu: [
        { role: 'undo' },
        { role: 'redo' },
        { type: 'separator' },
        { role: 'cut' },
        { role: 'copy' },
        { role: 'paste' },
        // { role: 'pasteandmatchstyle' },
        { role: 'delete' },
        // { role: 'selectall' }
      ]
    },
    {
      label: app.getName(), submenu: [
        {
          label: 'Reload', accelerator: 'CmdOrCtrl+R', click(item, focusedWindow) {
            // Electron 40: focusedWindow is now BaseWindow, cast to BrowserWindow for loadURL
            if (focusedWindow) (focusedWindow as BrowserWindow).loadURL(url.format(urlFormat))
          }
        },
        {
          label: 'Toggle Developer Tools',
          accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
          click(item, focusedWindow) {
            // Electron 40: focusedWindow is now BaseWindow, cast to BrowserWindow for webContents
            if (focusedWindow) (focusedWindow as BrowserWindow).webContents.toggleDevTools()
          }
        },
        { type: 'separator' },
        { role: 'quit' }
      ]
    }
  ]

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);

  session.defaultSession.webRequest.onBeforeSendHeaders({
    urls: ['https://graph.microsoft.com/*']
  }, (details, callback) => {
    delete details.requestHeaders['User-Agent'];
    
    details.requestHeaders['Host'] = 'localhost';
    callback({ requestHeaders: details.requestHeaders })
  })
}

// 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.
// protocol.registerStandardSchemes(['loehnapplication']);
protocol.registerSchemesAsPrivileged([
  { scheme: 'loehnapplication', privileges: { standard: true } }
]);
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X 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', function () {
  // On OS X 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 (mainWindow === null) {
    createWindow();
  }
});

/* handle IPC events here */

// open storage (PK => Ablage)
ipcMain.on('openStorage', (event: any, folder: string, companyPrefix: null | string, projectNumber: any, companyspecific:boolean=false, standard:boolean=false) => {
  if (projectNumber) {

    if (!companyPrefix) {
      companyPrefix = standard?"P":"";
    }

    const pkStorageFolderPath = folder || path.join(app.getPath('userData'), pkStorageFolderName);
    let pkCompanyStorageFolderPath;
    if(!companyspecific){
      pkCompanyStorageFolderPath = path.join(pkStorageFolderPath, companyPrefix);
    }
    else{
      pkCompanyStorageFolderPath=pkStorageFolderPath;
    }
    const projectStorageFolderPath = path.join(pkCompanyStorageFolderPath, String(projectNumber));

    if (!fs.existsSync(pkStorageFolderPath)) {
      fs.mkdirSync(pkStorageFolderPath);
    }

    if (!fs.existsSync(pkCompanyStorageFolderPath)) {
      fs.mkdirSync(pkCompanyStorageFolderPath);
    }

    if (!fs.existsSync(projectStorageFolderPath)) {
      fs.mkdirSync(projectStorageFolderPath);
    }

    shell.openPath(projectStorageFolderPath);
  }
});

ipcMain.on('openIndividualStorage', (event: any, folder: string, isUrl:boolean) => {
  if (fs.existsSync(folder) || isUrl) {
    shell.openPath(folder);
  }
});

ipcMain.on('openNotizapp', (event: any, folder: string, isUrl:boolean) => {
openOrFocus(folder, isUrl).catch(error => {
  console.error('Failed to open or focus:', error);
});
});

// open routines
ipcMain.on('openRoutines', (event: any, folder: string) => {

  const pkStorageFolderPath = folder || path.join(app.getPath('userData'), pkStorageFolderName);

  if (!fs.existsSync(pkStorageFolderPath)) {
    fs.mkdirSync(pkStorageFolderPath);
  }

  shell.openPath(pkStorageFolderPath);
});

ipcMain.on('getLocalStorage', (event: any) => {
  event.sender.send('getLocalStorageReply', path.join(app.getPath('userData'), pkStorageFolderName));
});



// Print function
ipcMain.on('printPage', (event: any, file: Buffer) => {
  
  saveBuffer(file, `export${new Date().getTime()}.pdf`, (localPath, err) => {
    if (err) {
      console.log('An error ocurred creating the file' + err.message);
    }
    else {
      shell.openPath(localPath);
      /*
      const PDFWindow = require('electron-pdf-window');
      const win = new BrowserWindow({ width: 800, height: 600, show: false })

      PDFWindow.addSupport(win);
      win.loadURL(localPath);
      win.webContents.on('did-finish-load', () => {
        function print() {
          let code = "var button = document.getElementById('print'); button.click()";
          win.webContents.executeJavaScript(code);
        }
        setTimeout(print, 1000);
      });
      */
    }
  }) 
});

function saveBuffer(buffer: Buffer, fileName: string, callback: (path: string, err: NodeJS.ErrnoException) => void) {    
    const pkStorageFolderPath = path.join(app.getPath('userData'), pkStorageFolderName);
    if (!fs.existsSync(pkStorageFolderPath)) {
      fs.mkdirSync(pkStorageFolderPath);
    }
    const localPath = pkStorageFolderPath + '/' + fileName;

    fs.writeFile(localPath, buffer, (err) => {
      callback(localPath, err)
    });
    /*fs.outputFile(fileName, buffer, err => {
      callback(fileName, err);
    });*/
}

//Store PDF File on disk
function storePdfFile(file: any, callback: (path: string, err: NodeJS.ErrnoException) => void) {

  const pkStorageFolderPath = path.join(app.getPath('userData'), pkStorageFolderName);
  if (!fs.existsSync(pkStorageFolderPath)) {
    fs.mkdirSync(pkStorageFolderPath);
  }
  const localPath = pkStorageFolderPath + `/export${new Date().getTime()}.pdf`;

  fs.writeFile(localPath, file, (err) => {
    callback(localPath, err)
  });
}

//Open child window
ipcMain.on('openChildWindow', (event: any, url: string) => {

  childWindow = new BrowserWindow({ parent: mainWindow, modal: true, show: false })
  
  childWindow.on('closed', (event: any, url: string) => {
    mainWindow.webContents.send('officeauth', { msg: 'error_subcode=cancel' });
    childWindow = null;
  });

  childWindow.loadURL(url)
  childWindow.once('ready-to-show', () => {
    childWindow.show();
  });

});

// select storage directory
ipcMain.on('getStorageDirectory', async (event: any, data: any) => {
  try {
    const selectedfolder = await dialog.showOpenDialog(mainWindow, { properties: ['openDirectory'] });

    event.sender.send('getStorageDirectoryReply', [data, selectedfolder.filePaths]);
  } catch (err) {
    console.error('Failed to open dialog:', err);
    event.sender.send('getStorageDirectoryReply', [data, []]);
  }
});

  // Handle Angular button click
  ipcMain.handle('open-quicknotes-window', async () => {
    return openQuicknotes();
  });

const quicknotesFilePath = path.join(app.getPath('userData'), 'quicknotes.txt');

function openQuicknotes(): Promise<string | null> {
  return new Promise((resolve) => {
    if (quicknotewindow) {
      quicknotewindow.focus();
      return resolve(null);
    }

    quicknotewindow = new BrowserWindow({
      width: 800,
      height: 600,
      parent: mainWindow,
      title: 'Schnellnotiz', 
      modal:process.platform==='darwin'? false:true,
      frame:true,
      titleBarStyle:'default',
      autoHideMenuBar: false,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: false,
      },
    });

    // Load HTML content directly (programmatically)
    const notesAvailable = fs.existsSync(quicknotesFilePath)
      ? fs.readFileSync(quicknotesFilePath, 'utf-8')
      : '';

    const html = `
      <!DOCTYPE html>
      <html>
      <head>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
      overflow: hidden; /* prevent body scroll */
    }
    textarea {
      background-color: #ffffd8;
      color: #000;
      width: 100%;
      height: 100%;
      box-sizing: border-box; 
      resize: none;          
      padding: 8px;
      font-size: 20px;
      font-family: "Segoe UI", Arial, sans-serif;
      overflow: auto;         /* enables scrollbar when content overflows */
      border: 2px solid #c7e3ff;
      outline: none;
    }
    textarea:focus {
      border-color: #b7dcff;
      box-shadow: 0 0 0 2px #d9ecff;
      outline: none;
    }
  </style>
</head>
<body>
<textarea id="notice">${notesAvailable}</textarea>
        <script>
          const { ipcRenderer } = require('electron');
          const textarea = document.getElementById('notice');

          // Auto-save every 5 seconds
          const autoSaveInterval = setInterval(() => {
            ipcRenderer.send('save-quicknotes', textarea.value);
          }, 5000);

          // Save on close
          window.addEventListener('beforeunload', () => {
            clearInterval(autoSaveInterval);
            ipcRenderer.send('save-quicknotes', textarea.value);
          });
        </script>
      </body>
      </html>
    `;

    quicknotewindow.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html));

    // Listen for content saves
    ipcMain.on('save-quicknotes', (event, content: string) => {
      fs.writeFileSync(quicknotesFilePath, content, 'utf-8');
    });

    quicknotewindow.on('closed', () => {
      quicknotewindow = null;
      resolve(fs.existsSync(quicknotesFilePath) ? quicknotesFilePath : null);
      ipcMain.removeAllListeners('save-quicknotes');
    });
  });
}