# Description:
#   enable communication with Phabricator via Conduit api
#
# Dependencies:
#
# Configuration:
#   PHABRICATOR_URL
#   PHABRICATOR_API_KEY
#   PHABRICATOR_PROJECTS
#   PHABRICATOR_BOT_PHID
#
# Commands:
#   hubot phab new <project> <name of the task> - creates a new task
#   hubot phab assign Txx to <user> - assigns task Txxx to comeone
#   hubot phab <user> - checks if user is known or not
#   hubot phab me as <email> - makes caller known with <email>
#   hubot phab <user> = <email> - associates user to email
#   hubot phab list projects - list known projects according to configuration
#   anything Txxx - complements with the title of the task, file (F) or paste (P)
#
# Author:
#   mose

Phabricator = require '../lib/phabricator'
moment = require 'moment'
path = require 'path'

phabColumns = { }
if process.env.PHABRICATOR_PROJECTS isnt undefined
  for list in process.env.PHABRICATOR_PROJECTS.split(',')
    [code, label] = list.split ':'
    phabColumns[label] = code

humanFileSize = (size) ->
  i = Math.floor( Math.log(size) / Math.log(1024) )
  return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]

module.exports = (robot) ->
  phab = new Phabricator robot, process.env

  # robot.respond /ph(?:ab)? create$/, (msg) ->
  #   id = 'T42'
  #   phab.recordPhid msg, id
  #   msg.finish()

  # robot.respond /ph(?:ab)? read$/, (msg) ->
  #   console.log phab.retrievePhid msg
  #   msg.finish()

  # robot.respond /ph(?:ab)? date$/, (msg) ->
  #   console.log moment(msg.message.user.lastTask).utc().format()
  #   console.log moment().utc().format()
  #   msg.finish()

  robot.respond (/ph(?:ab)? list projects$/), (msg) ->
    msg.send "Known Projects: #{Object.keys(phabColumns).join(', ')}"


  robot.respond /ph(?:ab)? version/, (msg) ->
    pkg = require path.join __dirname, '..', 'package.json'
    msg.send "hubot-phabs module is version #{pkg.version}"
    msg.finish()


  robot.respond (/ph(?:ab)? new ([-_a-zA-Z0-9]+) (.+)/), (msg) ->
    column = phabColumns[msg.match[1]]
    name = msg.match[2]
    if column?
      phab.createTask msg, column, name, (body) ->
        if body['error_info']?
          msg.send "#{body['error_info']}"
        else
          id = body['result']['object']['id']
          url = process.env.PHABRICATOR_URL + "/T#{id}"
          phab.recordPhid msg, id
          msg.send "Task T#{id} created = #{url}"
    else
      msg.send 'Command incomplete.'

  robot.respond /ph(?:ab)? paste (.*)$/, (msg) ->
    title = msg.match[1]
    phab.createPaste msg, title, (body) ->
      if body['error_info']?
        msg.send "#{body['error_info']}"
      else
        id = body['result']['object']['id']
        url = process.env.PHABRICATOR_URL + "/paste/edit/#{id}"
        phab.recordPhid msg, id
        msg.send "Paste P#{id} created = edit on #{url}"


  robot.respond (/ph(?:ab)? count ([-_a-zA-Z0-9]+)/), (msg) ->
    column = phabColumns[msg.match[1]]
    if column?
      phab.listTasks msg, column, (body) ->
        if Object.keys(body['result']).length is 0
          msg.send "#{msg.match[1]} has no tasks."
        else
          msg.send "#{msg.match[1]} has #{Object.keys(body['result']).length} tasks."
    else
      msg.send 'Command incomplete.'


  robot.respond /ph(?:ab)?(?: T([0-9]+) ?)?$/, (msg) ->
    id = msg.match[1] ? phab.retrievePhid(msg)
    unless id?
      msg.send "Sorry, you don't have any task active right now."
      msg.finish()
      return
    phab.taskInfo msg, id, (body) ->
      if body['error_info'] is undefined
        phab.withUserByPhid robot, body.result.ownerPHID, (owner) ->
          status = body.result.status
          priority = body.result.priority
          phab.recordPhid msg, id
          msg.send "T#{id} has status #{status}, " +
                   "priority #{priority}, owner #{owner.name}"
      else
        msg.send "oops T#{id} #{body['error_info']}"
    msg.finish()


  robot.respond /ph(?:ab)?(?: T([0-9]+))? (?:is )?(open|resolved|wontfix|invalid|spite)$/, (msg) ->
    id = msg.match[1] ? phab.retrievePhid(msg)
    unless id?
      msg.send "Sorry, you don't have any task active right now."
      msg.finish()
      return
    status = msg.match[2]
    phab.updateStatus msg, id, status, (body) ->
      if body['error_info'] is undefined
        msg.send "Ok, T#{id} now has status #{body['result']['statusName']}."
      else
        msg.send "oops T#{id} #{body['error_info']}"
    msg.finish()


  robot.respond new RegExp(
    'ph(?:ab)?(?: T([0-9]+))? (?:is )?(unbreak|broken|none|unknown|high|normal|low|urgent|wish)$'
  ), (msg) ->
    id = msg.match[1] ? phab.retrievePhid(msg)
    unless id?
      msg.send "Sorry, you don't have any task active right now."
      msg.finish()
      return
    priority = msg.match[2]
    phab.updatePriority msg, id, priority, (body) ->
      if body['error_info'] is undefined
        msg.send "Ok, T#{id} now has priority #{body['result']['priority']}"
      else
        msg.send "oops T#{id} #{body['error_info']}"
    msg.finish()


  robot.respond /ph(?:ab)? ([^ ]*)$/, (msg) ->
    name = msg.match[1]
    assignee = robot.brain.userForName(name)
    unless assignee
      msg.send "Sorry, I have no idea who #{name} is. Did you mistype it?"
      return
    phab.withUser msg, assignee, (userPhid) ->
      msg.send "Hey I know #{name}, he's #{userPhid}"


  robot.respond /ph(?:ab)? me as (.*@.*)$/, (msg) ->
    email = msg.match[1]
    msg.message.user.email_address = email
    robot.brain.save()
    msg.send "Okay, I'll remember your email is #{email}"


  robot.respond /ph(?:ab)? ([^ ]*) *?= *?([^ ]*@.*)$/, (msg) ->
    who = msg.match[1]
    email = msg.match[2]
    assignee = robot.brain.userForName(who)
    unless assignee
      msg.send "Sorry I have no idea who #{who} is. Did you mistype it?"
      return
    assignee.email_address = email
    msg.send "Okay, I'll remember #{who} email as #{email}"

  robot.respond new RegExp(
    'ph(?:ab)?(?: assign)? (?:([^ ]+)(?: (?:to|on) (T)([0-9]+))?|(?:T([0-9]+) )?(?:to|on) ([^ ]+))$'
  ), (msg) ->
    if msg.match[2] is 'T'
      who = msg.match[1]
      what = msg.match[3]
    else
      who = msg.match[5]
      what = msg.match[4]
    id = what ? phab.retrievePhid(msg)
    unless id?
      msg.send "Sorry, you don't have any task active right now."
      msg.finish()
      return
    assignee = robot.brain.userForName(who)
    if assignee?
      phab.withUser msg, assignee, (userPhid) ->
        phab.assignTask msg, id, userPhid, (body) ->
          if body['error_info'] is undefined
            msg.send "Ok. T#{id} is now assigned to #{assignee.name}"
          else
            msg.send "#{body['error_info']}"
    else
      msg.send "Sorry I don't know who is #{who}, can you .phab #{who} = <email>"
    msg.finish()


  robot.hear new RegExp(
    "(?:.+|^)(?:(#{process.env.PHABRICATOR_URL})/?| |^)(T|F|P)([0-9]+)"
  ), (msg) ->
    url = msg.match[1]
    type = msg.match[2]
    id = msg.match[3]
    switch type
      when 'T'
        phab.taskInfo msg, id, (body) ->
          if body['error_info']?
            msg.send "oops T#{id} #{body['error_info']}"
          else
            closed = ''
            if body['result']['isClosed'] is true
              closed = " (#{body['result']['status']})"
            if url?
              msg.send "T#{id}#{closed} - #{body['result']['title']} " +
                       "(#{body['result']['priority']})"
            else
              msg.send "#{body['result']['uri']}#{closed} - #{body['result']['title']} " +
                       "(#{body['result']['priority']})"
            phab.recordPhid msg, id
      when 'F'
        phab.fileInfo msg, id, (body) ->
          if body['error_info']?
            msg.send "oops F#{id} #{body['error_info']}"
          else
            size = humanFileSize(body['result']['byteSize'])
            if url?
              msg.send "F#{id} - #{body['result']['name']} " +
                       "(#{body['result']['mimeType']} #{size})"
            else
              msg.send "#{body['result']['uri']} - #{body['result']['name']} "+
                       "(#{body['result']['mimeType']} #{size})"
      when 'P'
        phab.pasteInfo msg, id, (body) ->
          if Object.keys(body['result']).length < 1
            msg.send "oops P#{id} was not found."
          else
            lang = ''
            if body['result'][0]['language'] isnt ''
              lang = " (#{body['result'][0]['language']})"
            if url?
              msg.send "P#{id} - #{body['result'][0]['title']}#{lang}"
            else
              msg.send "#{body['result'][0]['uri']} - #{body['result'][0]['title']}#{lang}"
