# Description:
#   abilità di asjon di usare la shell *nix
#
# Requires:
#   None
#
# Commands:
#   asjon run/esegui/shell git/yarn args...
#
# Author:
#   Enrico Fasoli (fazo96)

cp = require 'child_process'

nope = ['BZBZ 400-BAD-REQUEST', 'BZBZ DOES-NOT-COMPUTE',
        'BZBZ ADMIN-NOT-DETECTED', 'BZBZ IS-NOT-AUTHORIZED',
        'BZBZ ACCESS-DENIED']

isFromAdmin = (res) ->
  res.robot.adapterName is 'shell' or
  res.message.room.id is process.env.ADMIN_ROOM


runCmd = (cmd,res,cb) ->
  if res?.send? then res.send 'operazione in corso: '+cmd
  if process.env.TESTING_ASJON
    # Fingi di eseguire l'operazione
    if res?.send? then res.send 'operazione "completata": '+cmd
    if cb?.call? then cb null,'',''
  else cp.exec cmd, (err,stdout,stderr) ->
    if res?.send?
      if err
        res.send 'operazione fallita:\n'+stdout+stderr
      else
        res.send 'operazione completata:\n'+stdout
    if cb?.call? then cb err,stdout,stderr

module.exports = (robot) ->

  # Lancia i test all'avvio
  if process.env.AUTO_RUN_TESTS and process.env.ADMIN_ROOM
    dest = room: process.env.ADMIN_ROOM
    dest.send = (x) -> robot.send dest, x
    runCmd 'yarn test', dest

  if process.env.AUTO_INFORM_ON_START
    room = id: process.env.AUTO_INFORM_ON_START
    robot.messageRoom room, 'asjon avviato e operativo!'

  robot.respond /aggiornati|scarica (?:gli )?aggiornamenti/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    runCmd 'git pull && yarn install', res

  robot.respond /(?:controlla gli )?aggiornamenti/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    runCmd 'git fetch && git status', res

  robot.respond /(?:installa (?:le )?)?dipendenze/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    runCmd 'yarn install', res

  robot.respond /(?:esegui (?:i )?)?test/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    runCmd 'yarn test', res

  robot.respond /secret-kill-code/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    process.exit 0

  robot.respond /(emergency|reverse) shell|phone home/i, (res) ->
    return res.send res.random nope unless isFromAdmin res
    rhost  = process.env.REV_REMOTE_HOST
    rport  = process.env.REV_REMOTE_PORT        || 22
    rtport = process.env.REV_REMOTE_TUNNEL_PORT || 2200
    host   = process.env.REV_LOCAL_HOST         || "localhost"
    port   = process.env.REV_LOCAL_PORT         || 22
    key    = process.env.REV_KEY
    return res.send 'non è impostato nessun host' unless rhost?
    return res.send 'manca una chiave ssh' unless key?

    ssh = "ssh -R #{rtport}:#{host}:#{port} -i #{key} -p #{rport} #{rhost}"

    res.send "ok, apro una reverse shell #{rhost}:#{rtport} -> #{host}:#{port}"
    res.send "connettiti entro 10s"
    runCmd ssh, res, ->
      res.send "connessione chiusa. reverse shell terminata"

  robot.on 'githook', (data,params) ->
    if data.ref is 'refs/heads/master' and process.env.AUTO_KILL_ON_UPDATE
      dest = name: params.name, room: params.room
      res = send: (x) -> robot.send dest, x
      runCmd 'git pull && yarn install', res, ->
        robot.send dest, 'riavvio in 5 SECONDI'
        reboot = -> process.exit 0
        unless process.env.TESTING_ASJON
          # Non riavviare durante i test
          setTimeout reboot, 5000