#!/usr/bin/ruby
# written by Emil.
# Licensed under the GPLv3 only.
#
# SHORT GUIDE
#
# Press enter to check for new messages, blank lines from you won't be sent.
#
# -serv specifies server,
# -port specifies port,
# -name specifies your display name,
#
# Type "BYE" to stop it after it connects to the moon.
# Type Enter and nothing else to refresh the messages.
# Type messages and send them, hopefully everyone hears you just fine.
#
# Commands (which always begin with a forward slash):
#
# Commands must be near the beginning of messages, and will preform their respective action.
#
# BYE, QUIT - exits
# SAY       - says something verbatim
# CLEAR     - clears the terminal
# NICK...   - sets the nick
# RECONNECT - reconnects
# DELAY...  - sets delays

require 'socket'
require 'readline'

@serv = '7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion'
@port = 50000

@name = "anonymous"

def read_from(socket)
  begin # probably too large of a read size...
    puts socket.read_nonblock(2 << 16)
  rescue
  end
end

def post(socket, msg)
  update_prefix
  socket.puts(@prefix + msg)
end

def update_prefix
  date = Time.now.utc.strftime("%Y/%m/%d %k:%M:%S")
  @prefix = "<#{date} #{@name}> "
end

def connect
  puts "Connecting to " + @serv + ":" + @port.to_s + " as " + @name
  socket = TCPSocket.new(@serv, @port)
  if not socket
    puts "Failed to connect."
    exit 1
  end
  return socket
end

def main
  begin
    h = { "-name" => 1, "-nick" => 1, "-serv" => 2, "-port" => 3 }

    ARGV.each_with_index do |element,index|
      case h[element]
      when h["-name"]
        @name = ARGV[index + 1]
      when h["-serv"]
        @serv = ARGV[index + 1]
      when h["-port"]
        @port = ARGV[index + 1].to_i
      end
    end
  rescue
  end
  loop do
    begin
      socket = connect
      delay = 0

      h = { "BYE" => 1, "QUIT" => 1, "SAY" => 2, "CLEAR" => 3, "NAME" => 4, "NICK" => 4,
            "RC" => 5, "RECONNECT" => 5, "DELAY" => 6 }

      update_prefix
      while msg = Readline.readline(@prefix, true)
        if not msg.empty?
          msg.strip!
          word = msg.split(/^\/([\w]*)$|^([\w]*) (.*)$/)[1..]
          case h[word[0]]
          when h["BYE"]
            post(socket, "BYE")
            exit 0
          when h["CLEAR"]
            puts "\e[1;1H\e[2J"
          when h["NICK"]
            if not word[1].empty?
              @name = word[1]
            end
          when h["RC"]
            puts "reconnecting..."
            socket.close
            socket = connect
          when h["DELAY"]
            delay = word[1].to_i
          when h["SAY"]
            if not word.length > 1
              word.push("")
            end
            post(socket, word[1])
          else
            post(socket, msg)
          end
        end

        read_from(socket)
        sleep delay
        update_prefix
      end
    rescue (Errno::ECONNREFUSED Errno::EPIPE)
      puts "\n THE HOUSE IS ON FIRE."
    ensure
      puts "\nSTOPPING NOW."
      exit 1
    end
  end
end

main