require Rails.root.join('services', 'sql-api', 'sql_api')

class Api::Json::GeocodingsController < Api::ApplicationController
  ssl_required :create, :update

  before_filter :load_table, only: [:create, :estimation_for]

  # In seconds
  GEOCODING_SQLAPI_CALLS_TIMEOUT = 45

  def update
    @stats_aggregator.timing('geocodings.update') do

      begin
        geocoding = current_user.geocodings_dataset.where(id: params[:id]).first
        return head(401) unless geocoding && params[:state] == 'cancelled'
        @stats_aggregator.timing('save') do
          geocoding.cancel
        end
        render_jsonp(geocoding.reload)
      rescue StandardError => e
        render_jsonp({ errors: e.message }, 400)
      end

    end
  end

  def create
    @stats_aggregator.timing('geocodings.create') do

      begin
        geocoding  = Geocoding.new params.slice(:kind, :geometry_type, :formatter, :country_code, :region_code)
        geocoding.user = current_user
        geocoding.table_id = @table.try(:id)
        geocoding.table_name = params[:table_name] ? params[:table_name] : @table.try(:name)
        geocoding.raise_on_save_failure = true
        geocoding.force_all_rows = (params[:force_all_rows].to_s == 'true')

        geocoding.formatter = "{#{ params[:column_name] }}" if params[:column_name].present?

        geocoding = @stats_aggregator.timing('special-params') do
          # TODO api should be more regular
          unless ['high-resolution', 'ipaddress'].include? params[:kind] then
            if params[:text]
              countries = [params[:location]]
            else
              countries = @table.sequel.distinct.select_map(params[:location].to_sym)
              geocoding.country_column = params[:location]
            end
            geocoding.country_code = countries.map{|c| "'#{ c }'"}.join(',')

            if params[:region]
              if params[:region_text]
                regions = [params[:region]]
              else
                regions = @table.sequel.distinct.select_map(params[:region].to_sym)
                geocoding.region_column = params[:region]
              end
              geocoding.region_code = regions.map{|r| "'#{ r }'"}.join(',')
            end
          end
          geocoding
        end

        geocoding = @stats_aggregator.timing('save') do
          geocoding.save
          geocoding
        end

        Resque.enqueue(Resque::GeocoderJobs, job_id: geocoding.id)

        render_jsonp(geocoding.to_json)
      rescue Sequel::ValidationFailed => e
        CartoDB.notify_exception(e)
        render_jsonp( { description: e.message }, 422)
      rescue StandardError => e
        CartoDB.notify_exception(e)
        render_jsonp( { description: e.message }, 500)
      end

    end
  end

  protected

  def load_table
    @table = Carto::Helpers::TableLocator.new.get_by_id_or_name(params.fetch('table_name'), current_user).try(:service)
  end
end
