function Log (options) {
  this.levels = {
    'DEBUG': 5,
    'INFO': 4,
    'NOTICE': 3,
    'WARN': 2,
    'ERROR': 1,
    'FATAL': 0
  }
  this.options = options || {}
  if (this.options.loglevel) { // DEBUG, INFO, NOTICE, WARN, ERROR, FATAL
    this.loglevel = this.levels[this.options.loglevel]
  } else {
    this.loglevel = 2
  }
  if (this.options.name) {
    this.name = this.options.name
  } else {
    this.name = require('./package.json').name
  }
  if (this.options.hostname) {
    this.hostname = this.options.hostname
  } else {
    let os = require('os')
    this.hostname = os.hostname()
  }
  if (this.options.graylog && this.options.graylog.active) {
    if (this.options.graylog.mode && this.options.graylog.mode === 'http') {
      this.request = require('request')
    } else {
      this.udp = require('dgram')
      this.udpclient = this.udp.createSocket('udp4')
    }
  }
  if (this.options.file) {
    this.fs = require('fs')
    this.path = require('path')
    try {
      if (!this.fs.existsSync(this.options.path)) this.fs.mkdirSync(this.options.path, { recursive: true })
    } catch (error) {
      throw new Error('Could not create path ' + this.options.path + '\n' + error.toString())
    }
    try {
      this.fs.accessSync(this.path.join(this.options.path, this.options.file), this.fs.constants.R_OK | this.fs.constants.W_OK)
    } catch (err) {
      try {
        this.fs.writeFileSync(this.path.join(this.options.path, this.options.file), '', { flag: 'wx' })
      } catch (innerErr) {
        throw new Error('Could not Create File ' + this.options.file + '\n' + innerErr.toString())
      }
    }
  }
  this.info = function (message) {
    if (this.loglevel >= this.levels.INFO) {
      return this.log('INFO', message)
    } else {
      return ''
    }
  }
  this.notice = function (message) {
    if (this.loglevel >= this.levels.NOTICE) {
      return this.log('NOTICE', message)
    } else {
      return ''
    }
  }
  this.fatal = function (message) {
    if (this.loglevel >= this.levels.FATAL) {
      return this.log('FATAL', message)
    } else {
      return ''
    }
  }
  this.warn = function (message) {
    if (this.loglevel >= this.levels.WARN) {
      return this.log('WARN', message)
    } else {
      return ''
    }
  }
  this.error = function (message) {
    if (this.loglevel >= this.levels.ERROR) {
      return this.log('ERROR', message)
    } else {
      return ''
    }
  }
  this.debug = function (message) {
    if (this.loglevel >= this.levels.DEBUG) {
      return this.log('DEBUG', message)
    } else {
      return ''
    }
  }
  this.log = function (tag, message) {
    let msg = this.getDate() + '\t' + this.hostname + '\t' + this.name + '\t' + tag + '\t' + message
    switch (tag) {
      case 'INFO':
        console.info(msg)
        break
      case 'NOTICE':
        console.log(msg)
        break
      case 'WARN':
        console.warn(msg)
        break
      case 'ERROR':
        console.error(msg)
        break
      case 'FATAL':
        console.error(msg)
        break
      case 'DEBUG':
        console.log(msg)
        break
      default:
        console.log(msg)
    }
    if (this.options.path && this.options.file) {
      this.fs.appendFile(this.path.join(this.options.path, this.options.file), msg + '\n', function (error) {
        if (error) {
          console.error('Cannot write to File ' + this.options.file)
        }
      })
    }
    if (this.options.graylog && this.options.graylog.active) {
      let data = JSON.stringify({
        short_message: message,
        timestamp: Date.now() / 1000,
        host: this.hostname,
        facility: this.name,
        level: this.levels[tag]
        })
      if (this.options.graylog.mode && this.options.graylog.mode === 'http') {
        this.request.post(this.options.graylog.server + ':' + this.options.graylog.port + '/gelf', {json: JSON.parse(data)}, (error, res, body) => {
          if (error) {
            console.error(error)
          }
        })
      } else {
        this.udpclient.send(Buffer.from(data),this.options.graylog.port,this.options.graylog.server,function(error){
          if(error){
            console.error(error)
          }
        })
      }
    }
    return msg
  }
  this.getDate = function () {
    var tzoffset = (new Date()).getTimezoneOffset() * 60000 // offset in milliseconds
    var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -1)
    return localISOTime.split('.')[0].trim()
  }
  return this
}
module.exports = Log