require "rmagick"
require "digest"

class ImageUtils
  @@magickImg  = nil

  @@password   = ""
  @@message    = ""
  @@salt       = 0

  @@imagickImg = nil

  @@width      = 0
  @@height     = 0

  @@pixel_arr  = nil

  @@hash       = nil

  @@rng        = nil

  def initialize(pass, msg, uri)
    @@password = pass
    @@message  = msg
    @@salt     = 0

    @@magickImg = Magick::Image.read(uri).first

    @@width = @@magickImg.columns
    @@height = @@magickImg.rows

    @@pixel_arr = @@magickImg.get_pixels(0, 0, @@width, @@height)

    @@hash = self.generateHash

    # convert hex string into an int to store for making the lookup table
    @@rng = Random.new(@@hash.to_i(16))

    puts self.getLookupTable.inspect
  end

  def getPixel(x, y)
    loc = (y*@@width) + x

    return @@pixel_arr[loc]
  end

  def getSalt
    for x in 0..@@width-1
      for y in 0..@@height-1
        pix = self.getPixel(x, y)

        @@salt = @@salt + (pix.red/512)
        @@salt = @@salt + (pix.green/512)
        @@salt = @@salt + (pix.blue/512)
      end
    end

    h = Digest::SHA512.hexdigest(@@salt.to_s(16))

    return h
  end

  def generateHash
    pass_h = Digest::SHA512.hexdigest(@@password)

    return Digest::SHA512.hexdigest(pass_h + @@salt.to_s)
  end

  def getBits(o)
    msg_bytes = o.unpack("c*")

    msg_bits = 0

    for b in msg_bytes
      msg_bits = (msg_bits << 8) | b
    end

    return msg_bits
  end

  def getLookupTable
    tbl = []

    # track hash classes.  if too many occur during the interval, abaondon 
    # encoding.
    clashes = 0
    clash_limit = 100

    msg_bits = self.getBits(@@message)
 	
    while msg_bits > 0 do
      loc = nil

      loop do
        x = @@rng.rand(0..@@width)
        y = @@rng.rand(0..@@height)

        loc = {"x": x, "y": y}
        if !tbl.include?(loc) then
          clashes = 0
        else
          clashes = clashes + 1
        end

        if clashes < clash_limit then
          break
        else
          puts "wow clashed so much sorry for breaking"
          exit
        end
      end

      tbl.push(loc)

      msg_bits = msg_bits >> 6
    end

    return tbl
  end

  def getBits(o)
    msg_bytes = o.unpack("c*")

    msg_bits = 0

    for b in msg_bytes
      msg_bits = (msg_bits << 8) | b
    end

    return msg_bits
  end
end
