# frozen_string_literal: true

class Combustion::Databases::MySQL < Combustion::Databases::Base
  ACCESS_DENIED_ERROR = 10_145

  def reset
    establish_connection(configuration.merge(:database => nil))

    super
  end

  private

  def charset
    configuration[:charset] || ENV["CHARSET"] || "utf8"
  end

  def charset_error
    return "" unless configuration[:charset]

    "(if you set the charset manually, make sure you have a matching collation)"
  end

  def collation
    configuration[:collation] || ENV["COLLATION"] || "utf8_unicode_ci"
  end

  def create
    connection.create_database configuration[:database], creation_options
    establish_connection configuration
  rescue error_class => error
    rescue_create_from error
  end

  def create_as_root(error)
    establish_connection configuration.merge(
      :database => nil,
      :username => "root",
      :password => request_password(error)
    )

    connection.create_database configuration[:database], creation_options
    connection.execute grant_statement

    establish_connection configuration
  end

  def creation_options
    {:charset => charset, :collation => collation}
  end

  def drop
    connection.drop_database configuration[:database]
  end

  def error_class
    if configuration[:adapter][/jdbc/]
      # FIXME: After Jdbcmysql gives this class
      require "active_record/railties/jdbcmysql_error"
      ArJdbcMySQL::Error
    elsif configuration[:adapter][/mysql2/] && defined?(Mysql2)
      Mysql2::Error
    else
      Mysql::Error
    end
  end

  def grant_statement
    <<-SQL
GRANT ALL PRIVILEGES ON #{configuration["database"]}.*
TO '#{configuration[:username]}'@'localhost'
IDENTIFIED BY '#{configuration[:password]}' WITH GRANT OPTION;
    SQL
  end

  def request_password(error)
    print <<-TXT.strip
#{error.error}.
Please provide the root password for your mysql installation
>
    TXT

    $stdin.gets.strip
  end

  def rescue_create_from(error)
    if error.errno == ACCESS_DENIED_ERROR
      create_as_root(error)
      return
    end

    warn <<-TXT
#{error.error}
Couldn't create database for #{configuration.inspect}, charset: #{charset}, collation: #{collation}
#{charset_error}
    TXT
  end
end
