#!/usr/bin/env ruby

$LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
require 'pg_query'
require 'sqlint'
require 'optparse'

options = { limit: 1000 }
optparse = OptionParser.new do |opts|
  opts.banner = "Usage: #{File.basename($0)} [options] [file.sql ...]"
  opts.separator ""
  opts.separator "Options:"
  opts.on("--limit=N", Integer, "Limit checking to N errors (default: #{options[:limit]})") do |n|
    options[:limit] = n
  end
  opts.on_tail("-h", "--help", "Print this help") do
    puts opts
    exit 0
  end
  opts.on_tail("-v", "--version", "Display the version") do
    puts SQLint::VERSION
    exit 0
  end
end
optparse.parse!(ARGV)

ERROR_TYPES = {error: "ERROR", warning: "WARNING"}

class String
  def sanitise
    gsub(/[[:cntrl:]+]/) do |bad|
      bad.codepoints.map { |c| "\\%04d" % c }.join
    end
  end
end

def display_lint(lint)
  message_lines = lint.message.split("\n")
  puts [
    lint.filename,
    lint.line,
    lint.column,
    ERROR_TYPES[lint.type] + " " + message_lines.shift.sanitise
  ].join(":")
  message_lines.each do |line|
    puts "  " + line.sanitise
  end
end

def each_input_file(&block)
  if ARGV.empty?
    yield [STDIN, "stdin"]
  else
    ARGV.each do |filename|
      File.open(filename, 'r') do |file|
        yield [file, filename]
      end
    end
  end
end

saw_errors = false
each_input_file do |file, filename|
  results = SQLint::Linter.new(filename, file).run.first(options[:limit])
  results.each do |lint|
    display_lint(lint)
  end
  saw_errors ||= results.any? { |lint| lint.type == :error }
end

exit 1 if saw_errors
