import {ipcMain, ipcRenderer} from 'electron'
import util from 'util'
import {forwardLogs} from '../shared/local-debug'
import fs from 'fs'
import path from 'path'
import mkdirp from 'mkdirp'
import {logFileName} from '../shared/constants/platform.native.desktop.js'
import setupLocalLogs from '../shared/util/local-log'

const methods = ['log', 'error', 'info']
const originalConsole = {}
methods.forEach(k => {
  originalConsole[k] = console[k]
})

function fileDoesNotExist (err) {
  if (process.platform === 'win32' && err.errno === -4058) {
    return true
  }

  if (err.errno === -2) {
    return true
  }

  return false
}

const logLimit = 5e6
const logFile = logFileName()
let fileWritable = null
// If the file is too big, let's reset the log
if (logFile) {
  // ensure it exists
  mkdirp.sync(path.dirname(logFile))

  fs.access(logFile, fs.W_OK, err => {
    if (err && !fileDoesNotExist(err)) {
      console.log("Can't write to log file.", err)
      fileWritable = null
      return
    }

    fs.stat(logFile, (err, stat) => {
      if (err != null) {
        fileWritable = fs.createWriteStream(logFile)
        return
      }

      if (stat.size > logLimit) {
        fileWritable = fs.createWriteStream(logFile)
        return
      }

      fileWritable = fs.createWriteStream(logFile, {flags: 'a'})
    })
  })
}

function tee (...writeFns) {
  return t => writeFns.forEach(w => w(t))
}

const stdErrWriter = process.platform === 'win32' ? () => {} : t => process.stderr.write(t)
const stdOutWriter = process.platform === 'win32' ? () => {} : t => process.stdout.write(t)
const logFileWriter = t => fileWritable && fileWritable.write(t)

// override console logging to also go to stdout
const output = {
  error: tee(stdErrWriter, logFileWriter),
  log: tee(stdOutWriter, logFileWriter),
  warn: tee(stdOutWriter, logFileWriter),
}

export default function pipeLogs () {
  setupLocalLogs()

  if (!forwardLogs) {
    return
  }

  methods.forEach(k => {
    console[k] = (...args) => {
      if (args.length) {
        const out = output[k] || stdOutWriter
        out(`${k}: ${Date()} (${Date.now()}): ${util.format.apply(util, args)}\n`)
      }
    }
  })
}

export function ipcLogs () {
  // Simple ipc logging for debugging remote windows
  if (!forwardLogs) {
    return
  }

  ipcMain.on('console.log', (event, args) => {
    const prologue = `From ${event.sender.getTitle()}: `
    stdOutWriter(prologue)
    logFileWriter(prologue)
    console.log.apply(console, args)
  })

  ipcMain.on('console.warn', (event, args) => {
    const prologue = `From ${event.sender.getTitle()}: `
    stdOutWriter(prologue)
    logFileWriter(prologue)
    console.log.apply(console, args)
  })

  ipcMain.on('console.error', (event, args) => {
    const prologue = `From ${event.sender.getTitle()}: `
    stdOutWriter(prologue)
    logFileWriter(prologue)
    console.log.apply(console, args)
  })
}

export function ipcLogsRenderer () {
  const {logLocal, warnLocal, errorLocal} = setupLocalLogs()

  if (!forwardLogs) {
    return
  }

  window.console.log = (...args) => { try { logLocal(...args); ipcRenderer.send('console.log', args) } catch (_) {} }
  window.console.warn = (...args) => { try { warnLocal(...args); ipcRenderer.send('console.warn', args) } catch (_) {} }
  window.console.error = (...args) => { try { errorLocal(...args); ipcRenderer.send('console.error', args) } catch (_) {} }
}

@@ -704,84 +704,130 @@
 ull%0A
-// If the file is too big, let's reset the log%0Aif (logFile) %7B
+%0Afunction setupFileWritable () %7B%0A  if (!logFile) %7B%0A    console.log('No log file')%0A    return%0A  %7D
 %0A  // 
-e
+E
 nsure 
-it
+log directory
  exi
@@ -868,16 +868,65 @@
 File))%0A%0A
+  // Check if we can write to log file%0A  try %7B%0A  
   fs.acc
@@ -928,16 +928,20 @@
 s.access
+Sync
 (logFile
@@ -953,16 +953,23 @@
 W_OK
-, err =%3E
+)%0A  %7D catch (e)
  %7B%0A 
@@ -979,15 +979,8 @@
 if (
-err && 
 !fil
@@ -994,18 +994,16 @@
 tExist(e
-rr
 )) %7B%0A   
@@ -1017,18 +1017,24 @@
 ole.
-log(%22Can't
+error('Unable to
  wri
@@ -1051,74 +1051,83 @@
 file
-.%22, err)%0A      fileWritable = null%0A      return%0A    %7D%0A%0A   
+:', e)%0A      return%0A    %7D%0A  %7D%0A%0A  let stat = null%0A  try %7B%0A    stat =
  fs.stat
 (log
@@ -1122,24 +1122,28 @@
  fs.stat
+Sync
 (logFile
 , (err, 
@@ -1138,56 +1138,125 @@
 File
-, (err, stat) =%3E %7B%0A      if (err != null) %7B
+)%0A  %7D catch (e) %7B%0A    if (!fileDoesNotExist(e)) %7B%0A      console.error('Error getting status for log file:', e)
 %0A    
+%7D%0A
     
@@ -1292,36 +1292,32 @@
 Stream(logFile)%0A
-    
     return%0A     
@@ -1317,53 +1317,133 @@
 n%0A  
-    %7D%0A%0A      if (stat.size %3E logLimit) %7B%0A    
+%7D%0A%0A  // If the file is too big, let's reset the log%0A  if (stat.size %3E logLimit) %7B%0A    console.log('File too big, resetting')%0A
     
@@ -1487,20 +1487,16 @@
 ogFile)%0A
-    
     retu
@@ -1502,21 +1502,41 @@
 urn%0A
-    
   %7D%0A%0A  
-  
+// Append to existing log%0A
   fi
@@ -1596,21 +1596,30 @@
 '%7D)%0A
-    %7D)%0A  %7D)%0A%7D
+%7D%0A%0AsetupFileWritable()
 %0A%0Afu

Fix file logging on startup (Electron) (#3807)