#
#   Copyright (C) Stonesoft Corporation 2010 - 2013.
#   All rights reserved.
#
#   The StoneGate software, manuals, and technical
#   literature may not be reproduced in any form or
#   by any means except by permission in writing from
#   Stonesoft Corporation.
#

ERROR = 3
WARN = 2
INFO = 1
DEBUG = 0
if $DEBUG
  $log_lvl = DEBUG
else
  $log_lvl = INFO
end

LOG_MAP = {ERROR => "ERROR", WARN => "WARN ", INFO => "INFO ", DEBUG => "DEBUG"}

if $log_file.nil?
  $log_file = File.new("#{$0}.log", "a")
end

# log one complete line with header
def log(message, lvl = INFO)
  if lvl >= $log_lvl
    time = Time.new.strftime("%Y-%m-%d %H:%M:%S")
    code = LOG_MAP[lvl]
    str = time + " " + code + " " + message
    puts str
    $stdout.flush
    $log_file.puts str
    $log_file.flush
  end
end

# log line without header
def log_no_header(message, lvl = INFO)
  if lvl >= $log_lvl
    puts message
    $stdout.flush
    $log_file.puts message
    $log_file.flush
  end
end

# log line with header but no line feed
def log_header(message, lvl = INFO)
  if lvl >= $log_lvl
    time = Time.new.strftime("%Y-%m-%d %H:%M:%S")
    code = LOG_MAP[lvl]
    str = time + " " + code + " " + message
    print str
    $stdout.flush
    $log_file.print str
    $log_file.flush
  end
end

# log message without line feed
def log_nlf(message, lvl = INFO)
  if lvl >= $log_lvl
    print message
    $stdout.flush
    $log_file.print message
    $log_file.flush
  end
end

### ATFExpect

begin
  require "pty"
rescue Exception
  # on windows this wont work but so what
end
require "timeout"

class ATFExpect
  attr_accessor :time_out, :pid
  attr_reader :read, :write 

  def initialize(cmd, timeout = 15)
    @time_out = timeout
    @read = nil
    @write = nil
    @pid = nil

    read, write, pid = PTY.spawn( cmd )
    read.sync = true
    write.sync = true
    @write = write
    @pid = pid
    @read = read
  end

  def close
    begin
      @read.close
      @write.close
    rescue IOError
    end
    begin
      Process.wait @pid
    rescue PTY::ChildExited
    rescue TypeError
    rescue Errno::ECHILD
    end
  end

  def expect_line(regex)
    str = ""
    while(true)
      line = @read.gets
      str += line
      break if line =~ regex
    end
    return str
  end

  def expect(regex, time_out = @time_out, size_hint = 0)
    if regex.instance_of?(String)
      regex = /#{regex}/
    end
    # wait for a max 120 sec until accepting that the spawn command has failed
    timeout(120) do
      while not @read
        sleep 0.1 # wait for cmd to be initialized
      end
    end
    res = ""
    begin
      timeout(time_out) do
        while(true)
          begin
            res << @read.sysread(1).to_s #read one at a time
          rescue EOFError
            sleep 0.5
            retry
          rescue => exc
            raise exc
          end
          if (size_hint == 0 or res.size > size_hint) and res =~ regex
            break
          end
        end
      end
    rescue Timeout::Error => e
      new_e = Timeout::Error.new(e.message + " (was waiting for #{regex} but got #{res})")
      new_e.set_backtrace(e.backtrace)
      raise new_e
    rescue PTY::ChildExited
      log "spawn pty child exited in expect method !!", DEBUG
    end
    res
  end

  def send(str)
    @write.print(str) unless @write == nil
  end

  def kill()
    if not @pid.nil?
      `kill -INT #{@pid} 2>&1; kill -INT #{@pid} 2>&1`
      @pid = nil
    end
  end

  def flush(get_garbage = false)
    garbage = ""
    return "spawn pty child exited, no garbage collected" if @read == nil
    begin
      timeout(0.1) do
        while(not @read.eof?)
          garbage << @read.read(16).to_s
        end
      end
    rescue Timeout::Error
    rescue PTY::ChildExited
      flush
    end
    @write.flush
    return garbage unless garbage.empty? if get_garbage
  end
end

module IPForge
  class IPForgeException < Exception
  end
  class BrokenAddressException < IPForgeException
  end
end
