# frozen_string_literal: true

#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'shell/formatter'

module Shell
  module Commands
    # rubocop:disable Metrics/ClassLength
    # Base class for all HBase shell commands
    class Command
      def initialize(shell)
        @shell = shell
      end

      # gets the name that an operator would type into the shell

      def command_name
        klass_name = self.class.name.split('::').last
        klass_name.gsub(/([^\^])([A-Z])/, '\1_\2').downcase
      end

      # wrap an execution of cmd to catch hbase exceptions
      # cmd - command name to execute
      # args - arguments to pass to the command

      # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
      def command_safe(debug, cmd = :command, *args)
        # Commands can overwrite start_time to skip time used in some kind of setup.
        # See count.rb for example.
        @start_time = Time.now
        # send is internal ruby method to call 'cmd' with *args
        # (everything is a message, so this is just the formal semantics to support that idiom)
        translate_hbase_exceptions(*args) { send(cmd, *args) }
      rescue StandardError => e
        root_cause = e

        # JRuby9000 made RubyException respond to cause, ignore it for back compat
        while !root_cause.is_a?(Exception) && root_cause.respond_to?(:cause) &&
              !root_cause.cause.nil?
          root_cause = root_cause.cause
        end
        return raise root_cause unless @shell.interactive?

        puts
        puts "ERROR: #{root_cause}"
        puts "Backtrace: #{root_cause.backtrace.join("\n           ")}" if debug
        puts
        puts "For usage try 'help \"#{command_name}\"'"
        puts
      ensure
        # If end_time is not already set by the command, use current time.
        @end_time ||= Time.now
        formatter.output_str(format('Took %.4f seconds', @end_time - @start_time))
      end
      # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity

      # Convenience functions to get different admins
      # Returns HBase::Admin ruby class.
      def admin
        @shell.admin
      end

      def taskmonitor
        @shell.hbase_taskmonitor
      end

      def table(name)
        @shell.hbase_table(name)
      end

      def replication_admin
        @shell.hbase_replication_admin
      end

      def security_admin
        @shell.hbase_security_admin
      end

      def visibility_labels_admin
        @shell.hbase_visibility_labels_admin
      end

      def quotas_admin
        @shell.hbase_quotas_admin
      end

      def rsgroup_admin
        @shell.hbase_rsgroup_admin
      end

      #----------------------------------------------------------------------
      # Creates formatter instance first time and then reuses it.
      def formatter
        @formatter ||= ::Shell::Formatter::Console.new
      end

      # for testing purposes to catch the output of the commands
      attr_writer :formatter

      # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
      def translate_hbase_exceptions(*args)
        yield
      rescue StandardError => e
        cause = e
        # let individual command handle exceptions first
        cause = cause.getCause if cause.is_a? java.io.UncheckedIOException

        handle_exceptions(cause, *args) if respond_to?(:handle_exceptions)
        # Global HBase exception handling below if not handled by respective command above
        if cause.is_a?(org.apache.hadoop.hbase.TableNotFoundException)
          strs = cause.to_s.split(' ')
          raise "Unknown table #{strs[0]}!" if strs.size == 1

          raise "Unknown table #{args.first}!"
        end
        if cause.is_a?(org.apache.hadoop.hbase.TableNotEnabledException)
          raise "Table #{args.first} is disabled!"
        end
        if cause.is_a?(org.apache.hadoop.hbase.TableNotDisabledException)
          raise "Table #{cause.message} should be disabled!"
        end

        raise cause.message if cause.is_a?(org.apache.hadoop.hbase.UnknownRegionException)

        if cause.is_a?(org.apache.hadoop.hbase.exceptions.MergeRegionException)
          strs = cause.message.split("\n")
          raise strs[0].to_s unless strs.empty?
        end

        if cause.is_a?(org.apache.hadoop.hbase.NamespaceNotFoundException)
          s = /.*NamespaceNotFoundException: (?<namespace>[^\n]+).*/.match(cause.message)

          raise "Unknown namespace #{s['namespace']}!"
        end
        if cause.is_a?(org.apache.hadoop.hbase.snapshot.SnapshotDoesNotExistException)
          raise "Unknown snapshot #{args.first}!"
        end

        if cause.is_a?(org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException)
          exceptions = cause.getCauses
          exceptions.each do |exception|
            next unless exception.is_a?(
              org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException
            )

            valid_cols = table(args.first).get_all_columns.map { |c| "#{c}*" }
            raise "Unknown column family! Valid column names: #{valid_cols.join(', ')}"
          end
        end
        if cause.is_a?(org.apache.hadoop.hbase.TableExistsException)
          strs = cause.to_s.split(' ')
          raise "Table already exists: #{strs[0]}!" if strs.size == 1

          raise "Table already exists: #{args.first}!"
        end
        # To be safe, here only AccessDeniedException is considered. In future
        # we might support more in more generic approach when possible.
        if cause.is_a?(org.apache.hadoop.hbase.security.AccessDeniedException)
          str = java.lang.String.new(cause.to_s)
          # Error message is merged with stack trace, reference StringUtils.stringifyException
          # This is to parse and get the error message from the whole.
          strs = str.split("\n")
          raise strs[0].to_s unless strs.empty?
        end
        if cause.is_a?(org.apache.hadoop.hbase.quotas.SpaceLimitingException)
          strs = cause.message.split("\n")
          raise(strs[0]).to_s unless strs.empty?
        end
        if cause.is_a?(org.apache.hadoop.hbase.client.RetriesExhaustedException)
          str = cause.cause.to_s
          regex = /.*RpcThrottlingException: (?<message>[^\n]+).*/
          error = regex.match(str)
          raise error[:message].capitalize unless error.nil?
        end
        if cause.is_a?(org.apache.hadoop.hbase.DoNotRetryIOException)
          regex = /.*UnsupportedOperationException: quota support disabled.*/
          error = regex.match(cause.message)
          error_msg = 'Quota Support disabled. Please enable in configuration.'
          raise error_msg unless error.nil?
        end

        # Throw the other exception which hasn't been handled above
        raise cause
      end
      # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
    end
    # rubocop:enable Metrics/ClassLength
  end
end
