# frozen_string_literal: true

require 'yaml' require 'colorize' require 'tmpdir' require 'rspec/hive' require 'erb'

namespace :spec do

namespace :hive do
  namespace :config do
    desc 'Generates example config file. Accepts directory to file.'
    task :generate_default do
      require 'rbconfig'

      default_config = RSpec::Hive::Configuration.new

      default_values = {
        'hive' =>
          {
            'host' => ENV['HOST'] || default_config.host,
            'port' => ENV['PORT'] || default_config.port,
            'host_shared_directory_path' =>
              ENV['HOST_SHARED_DIR'] || default_config.host_shared_directory_path,
            'docker_shared_directory_path' =>
              ENV['DOCKER_SHARED_DIR'] || default_config.docker_shared_directory_path,
            'hive_version' =>
              ENV['HIVE_VERSION'] || default_config.hive_version,
            'hive_options' => {
              'hive.exec.dynamic.partition' => 'true',
              'hive.exec.dynamic.partition.mode' => 'nonstrict',
              'hive.exec.max.dynamic.partitions.pernode' => '100000',
              'hive.exec.max.dynamic.partitions' => '100000',
              'mapred.child.java.opts' => '-Xmx2048m'
            }
          }
      }
      system 'mkdir', '-p', default_values['hive']['host_shared_directory_path']
      system 'mkdir', '-p', 'config'

      file_path = ENV['CONFIG_FILE'] || File.join('config', 'rspec-hive.yml')

      File.open(file_path, 'w+') do |f|
        f.write default_values.to_yaml
        puts "Default config written to #{f.path}".green
      end
    end
  end

  namespace :docker do
    desc 'Runs docker using hive config file.'\
          ' It assumes your docker-machine is running.'
    task :run do
      raise 'Command `docker` not found.'.red unless system('which docker')

      config_filepath = ENV['CONFIG_FILE'] || File.join('config', 'rspec-hive.yml')
      unless File.exist? config_filepath
        raise "There's no config file #{config_filepath} please"\
             'generate default or provide custom config.'.red
      end

      interpolated = ERB.new(File.read(config_filepath)).result
      config = YAML.safe_load(interpolated)['hive']

      docker_image_name = ENV['DOCKER_IMAGE_NAME'] || 'nielsensocial/hive'
      cmd = "docker run -v #{config['host_shared_directory_path']}:"\
            "#{config['docker_shared_directory_path']}"\
            " -d -p #{config['port']}:10000 #{docker_image_name}"

      puts "Running `#{cmd}`...".green
      system(cmd)
    end

    desc 'Downloads docker image from dockerhub.'
    task :download_image do
      raise 'Command `docker` not found.'.red unless system('which docker')

      docker_image_name = ENV['DOCKER_IMAGE_NAME'] || 'nielsensocial/hive'

      cmd = "docker pull #{docker_image_name}"
      puts "Running `#{cmd}`...".green
      system(cmd)
    end

    def container_id
      return ENV['CONTAINER_ID'] if ENV['CONTAINER_ID']
      docker_conatiners = `docker ps`.lines
      if docker_conatiners.size != 2
        raise 'There is more than 1 instance of docker container running (or no running docker containers). '\
              'Check `docker ps` and stop containers that are not in use right now or specify CONTAINER_ID '\
              'and run this command again.'.red
      else
        docker_conatiners[1].split[0]
      end
    end

    desc 'Load Hive UDFS (user defined functions) onto docker.'
    task :load_udfs, [:udfs_path] do |_t, args|
      udfs_path = args[:udfs_path]
      config_filepath = ENV['CONFIG_FILE'] || File.join('config', 'rspec-hive.yml')
      interpolated = ERB.new(File.read(config_filepath)).result
      config = YAML.safe_load(interpolated)['hive']

      host_hive_udfs_path = File.join(config['host_shared_directory_path'], 'hive-udfs.jar')
      raise 'Please provide UDFS_PATH'.red unless udfs_path
      if udfs_path.start_with?('s3://')
        puts 'Downloading from s3...'.yellow
        cmd = "aws s3 ls #{udfs_path}"

        raise 'awscli is not configured.'.red unless system(cmd)
        cmd = "aws s3 cp #{udfs_path} #{host_hive_udfs_path}"
      else
        puts 'Copying from local directory...'.yellow
        cmd = "cp #{udfs_path} #{host_hive_udfs_path}"
      end
      system(cmd)
      puts 'Done'.green

      puts 'Copying to hadoop on docker...'.yellow
      cmd = "docker exec -it #{container_id} /bin/bash -c 'cp #{host_hive_udfs_path} $HADOOP_HOME'"
      system(cmd)
      puts 'Done'.green
    end
  end

  desc 'Runs beeline console on hive.'
  task :beeline do
    puts "Connecting to docker container: #{container_id} and running beeline. To exit: '!q'".green
    bash_cmd = '$HIVE_HOME/bin/beeline -u jdbc:hive2://localhost:10000 -d org.apache.hive.jdbc.HiveDriver'
    cmd = "docker exec -it #{container_id} /bin/bash -c #{bash_cmd}"
    system(cmd)
  end
end

end