import { Logger, transports } from 'winston'
import partial from 'lodash/partial'

export function use(options = {}, next) {
  if(this.logger) {
    next()
  } else {
    attach.call(this, this, options)
    next()
  }
}

export function attach(project, options = {}) {
  const {
    debug = !!project.get('environment.DEBUG', !!project.get('argv.debug', false)),
    enableConsole = !!project.get('environment.SKYPAGER_CONSOLE_LOGGING', !!project.get('argv.enableConsole', false)),
    logPath = project.get('argv.logPath', project.resolve(project.paths.logs)),
    name = 'project',
    timestamp = !!project.get('argv.logTimestamps', true),
    json = !!project.get('argv.logJson', false),
    prettyPrint = !!project.get('argv.pretty', true),
    streamLogs = project.getOption('streamLogs', project.get('argv.streamLogs', project.get('environment.SKYPAGER_STREAM_LOGS', false))),
  } = options

  let _transports = [
    new transports.File({
      name,
      filename: project.resolve(logPath, `project.${project.env}.log`), 
      timestamp,
      json,
      prettyPrint,
      maxSize: 1024
    })
  ]

  if (enableConsole) {
    _transports.push(
      new transports.Console({
        name: 'console',
        colorize: true,
        prettyprint,
        level: debug ? 'debug' : 'info'
      })
    )
  }

  project.hide(
    'logger',
    new Logger({ level: 'debug', transports: _transports }),
    true
  )

  if(streamLogs) {
    project.hide(
      'streamer',
      new Logger({ level: 'debug', transports: [
        new transports.File({
          name: `json`,
          filename: project.resolve(logPath, `${project.env}-${project.name}.json.log`),
          timestamp,
          json,
          prettyPrint,
        }),
        new transports.File({
          name: `pretty-json-stream`,
          filename: project.resolve(logPath, `${project.env}-${project.name}.pretty.json.log`),
          timestamp: true,
          json: true,
          prettyPrint: true,
          colorize: true,
        })
      ]}),
      true
    )
  }

  project.lazy('ensureLogsDir', () => project.mkdirpSync(logPath)) 

  project.hide('info', (...args) => {
    project.ensureLogsDir
    project.logger.info(...args)
    streamLogs && project.streamInfo(...args)
  })


  project.hide('error', (...args) => {
    project.ensureLogsDir
    project.logger.error(...args)
    streamLogs && project.streamError(...args)
  })

  project.hide('debug', (...args) => {
    project.ensureLogsDir
    project.logger.debug(...args)
    streamLogs && project.streamDebug(...args)   
  })

  project.hide('log', (...args) => {
    project.ensureLogsDir
    project.logger.info(...args)
    streamLogs && project.streamDebug(...args)   
  })

  project.hide('warn', (...args) => {
    project.ensureLogsDir
    project.logger.warn(...args)
    streamLogs && project.streamWarning(...args)
  })

  if (streamLogs) {
    project.ensureLogsDir
    project.hide('streamInfo', (...args) => project.streamer.info(...args))
    project.hide('streamDebug', (...args) => project.streamer.debug(...args))
    project.hide('streamLog', (...args) => project.streamer.log(...args))
    project.hide('streamError', (...args) => project.streamer.error(...args))
    project.hide('streamWarning', (...args) => project.streamer.warn(...args))
  }

  return project
}

export default attach

const { assign, defineProperty } = Object
