require 'stardog'
require 'time'
require 'uri'
require 'securerandom'

class Array
  attr_accessor :triples_id
  # When using an array of arrays to hold list of triples,
  # returns the first triple subject.
  def triples_id
    @triples_id || self.first.first
  end
end

module GRel

  # Exception raised to signal a validation error due to a
  # Stardog ICV.
  class ValidationError < Stardog::ICVException
    attr_accessor :icv_exception
    def initialize(msg, exception)
      super(msg)
      @icv_exception = exception
    end
  end

  DEBUG = ENV["GREL_DEBUG"] || false

  # Wrapper for the debugging logger method.
  class Debugger
    def self.debug(msg)
      puts msg if DEBUG
    end
  end

  # Common namespace for all URIs generated by GRel.
  NAMESPACE = "http://grel.org/vocabulary#"
  # Used to match valid ID strings
  ID_REGEX = /^\@id\((\w+)\)$/
  # A URI denoting a ruby nil value
  NIL = "\"http://www.w3.org/1999/02/22-rdf-syntax-ns#nil\""
  BNODE = "BNODE"

  # XML Scheam NonNegativeInteger type
  class NonNegativeInteger

    # Just wraps a numeric type
    def initialize(number)
      @number = number
    end

    def method_missing(name, *args, &blk)
      ret = @number.send(name, *args, &blk)
      ret.is_a?(Numeric) ? MyNum.new(ret) : ret
    end

    def to_s
      "\"#{@number}\"^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger>"
    end

  end

  # RDF Blank nodes
  class BlankId 

    # The ID of the blank node.
    attr_reader :blank_id

    # Creates a new BlankId object with an unique ID for
    # this execution.
    def initialize
      @blank_id = BlankId.next_id
    end

    # Unique IDs generator.
    def self.next_id
      next_id = (@counter ||= 0)
      @counter += 1
      next_id
    end

    # Turtle represenation of the blank node.
    def to_s
      "_:#{@blank_id}"
    end
  end

  # Creates a new graph object connected to the provided Stardog server.
  # Arguments:
  # - name : connection string. localhost:5822 by default.
  # - options: hash of options:
  #    + user : user name for authentication
  #    + password : password for authentication
  #    + validate : should validate integrity constraints
  #    + db : name of the db to use
  # Returns the newly built graph object.
  def graph(name='http://localhost:5822/',options = {})
    options[:user] ||= "admin"
    options[:password] ||= "admin"
    options[:validate] ||= false
    g = Base.new(name, options)
    g.with_db(options[:db]) if(options[:db])
    g
  end

end # end of module GRel

# remaining modules
require File.join(File.dirname(__FILE__), "grel", "ql")
require File.join(File.dirname(__FILE__), "grel", "base")
