# require "set"
require "toolhound-ruby/authentication"
require "toolhound-ruby/configurable"
require "toolhound-ruby/client/projects"
# require "toolhound-ruby/incident"


module Toolhound

  class Client
    include Toolhound::Authentication
    include Toolhound::Configurable
    include Toolhound::Util
    include Toolhound::Client::Projects
    # include Toolhound::Client::Bookmarks
    # include Toolhound::Client::Categories
    # include Toolhound::Client::Incidents
    # include Toolhound::Client::Notifications
    # include Toolhound::Client::Projects
    # include Toolhound::Client::RateLimit
    # include Toolhound::Client::Users
    # include Toolhound::Client::Companies
    # include Toolhound::Client::Attachments

    # include Toolhound::Client::Users
    # include Toolhound::Client::ProjectLibrary
    # include Toolhound::Client::Projects
    # include Toolhound::Client::Templates
    # include Toolhound::Client::Checklists
    # include Toolhound::Client::Tasks
    # include Toolhound::Client::Issues
    # include Toolhound::Client::Utils

    # def projects
    #
    # end
    # attr_accessor :access_token, :client_id, :uid, :expiry, :me
    attr_accessor :connection, :dataserver, :username, :password, :port

    def initialize(options = {})

      # Use options passed in, but fall back to module defaults
      Toolhound::Configurable.keys.each do |key|
        instance_variable_set(:"@#{key}", options[key] || Toolhound.instance_variable_get(:"@#{key}"))
      end

      sign_in if authenticatable?
    end

    # Compares client options to a Hash of requested options
    #
    # @param opts [Hash] Options to compare with current client options
    # @return [Boolean]
    def same_options?(opts)
      opts.hash == options.hash
    end


    def inspect # :nodoc:

      inspected = super

      # mask password
      inspected = inspected.gsub! @password, "*******" if @password
      # Only show last 4 of token, secret
      # if @access_token
      #   inspected = inspected.gsub! @access_token, "#{'*'*36}#{@access_token[36..-1]}"
      # end
      # if @client_secret
      #   inspected = inspected.gsub! @client_secret, "#{'*'*36}#{@client_secret[36..-1]}"
      # end

      inspected
    end

    def connection
      if @connection && @connection.dead?
        sign_in
      end
      @connection
    end


    # Set username for authentication
    #
    # @param value [String] Toolhound-field username
    def username=(value)
      reset_connection
      @email = value
    end

    # Set password for authentication
    #
    # @param value [String] Toolhound-field password
    def password=(value)
      reset_connection
      @password = value
    end

    def reset_connection
      @connection = nil
    end

    def job
      @job ||= Toolhound::Job.new(self)
    end

    def transaction
      @transaction ||= Toolhound::Transaction.new(self)
    end
    
    def inventory
      @inventory ||= Toolhound::Inventory.new(self)
    end

    def inventory_item
      @inventory_item ||= Toolhound::InventoryItem.new(self)
    end

    def project
      @project ||= Toolhound::Project.new(self)
    end

    def rental
      @rental ||= Toolhound::Rental.new(self)
    end

    def rental_item
      @rental_item ||= Toolhound::RentalItem.new(self)
    end
    def rental_charge
      @rental_charge ||= Toolhound::RentalCharge.new(self)
    end

    def vendor
      @vendor ||= Toolhound::Vendor.new(self)
    end
    def manufacturer
      @vendor ||= Toolhound::Manufacturer.new(self)
    end
    def purchase_order
      @vendor ||= Toolhound::PurchaseOrder.new(self)
    end



    def query(query, options = {})
      klass = self



      results = connection.execute(query)
      results.map do |row|
        transform_attributes(row)
      end
    end

    def transform_attributes(attrs)
      hash = {}
      attrs.each do |k, v|
        key = transform_attribute_key(k)
        if hash.include? key
          hash[:"#{key}1"] = v
        else
          hash[key] = v
        end
      end
      hash
    end

    DB_TYPE_REGEX = /^(int|dec|var|bol|dte|bin)/

    #"SELECT column_name, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tblRentalCharge' AND TABLE_SCHEMA='dbo'"

    # "SELECT * FROM information_schema.tables ORDER BY table_name"
    #
    # Find project from job number
    # "SELECT tblEntity.intEntityID, tblEntity.varEntityID AS job_no, tblLocation.intLocationID, tblLocationText.varLocationName  FROM tblEntity INNER JOIN tblLocation ON tblLocation.intEntityID = tblEntity.intEntityID INNER JOIN tblLocationText ON tblLocationText.intLocationID = tblLocation.intLocationID WHERE varEntityID LIKE '%10526.00%' "

    # "SELECT MAX(dteStartDate) AS max_date, MIN(dteStartDate) AS min_date FROM tblRentalCharge WHERE intEntityID  = 100044"
    #
    def transform_attribute_key(key)
      # renamed = self.class.renamed_attributes
      # if renamed.include? key
      #   renamed[key].to_sym
      # elsif key == self.class.primary_key
      #   :id
      # else
      # # "varTransferReceiptPrefix"
      #   word = key[3..key.length]
      #   word.underscore.to_sym
      # end
      word = key
      if DB_TYPE_REGEX =~ key
        word = key[3..key.length]
      end
      underscore(word).to_sym
    end


    # Wrapper around Kernel#warn to print warnings unless
    # TOOLHOUND_SILENT is set to true.
    #
    # @return [nil]
    def nearmiss_warn(*message)
      unless ENV['TOOLHOUND_SILENT']
        warn message
      end
    end



  end


end