text: import json
  import re
  
  from moto.core.responses import BaseResponse
  from moto.events import events_backends
  
  
  class EventsHandler(BaseResponse):
  
      @property
      def events_backend(self):
          """
          Events Backend
  
          :return: Events Backend object
          :rtype: moto.events.models.EventsBackend
          """
          return events_backends[self.region]
  
      def _generate_rule_dict(self, rule):
          return {
              'Name': rule.name,
              'Arn': rule.arn,
              'EventPattern': rule.event_pattern,
              'State': rule.state,
              'Description': rule.description,
              'ScheduleExpression': rule.schedule_exp,
              'RoleArn': rule.role_arn
          }
  
      @property
      def request_params(self):
          if not hasattr(self, '_json_body'):
              try:
                  self._json_body = json.loads(self.body)
              except ValueError:
                  self._json_body = {}
          return self._json_body
  
      def _get_param(self, param, if_none=None):
          return self.request_params.get(param, if_none)
  
      def error(self, type_, message='', status=400):
          headers = self.response_headers
          headers['status'] = status
          return json.dumps({'__type': type_, 'message': message}), headers,
  
      def delete_rule(self):
          name = self._get_param('Name')
  
          if not name:
              return self.error('ValidationException', 'Parameter Name is required.')
          self.events_backend.delete_rule(name)
  
          return '', self.response_headers
  
      def describe_rule(self):
          name = self._get_param('Name')
  
          if not name:
              return self.error('ValidationException', 'Parameter Name is required.')
  
          rule = self.events_backend.describe_rule(name)
  
          if not rule:
              return self.error('ResourceNotFoundException', 'Rule test does not exist.')
  
          rule_dict = self._generate_rule_dict(rule)
          return json.dumps(rule_dict), self.response_headers
  
      def disable_rule(self):
          name = self._get_param('Name')
  
          if not name:
              return self.error('ValidationException', 'Parameter Name is required.')
  
          if not self.events_backend.disable_rule(name):
              return self.error('ResourceNotFoundException', 'Rule ' + name + ' does not exist.')
  
          return '', self.response_headers
  
      def enable_rule(self):
          name = self._get_param('Name')
  
          if not name:
              return self.error('ValidationException', 'Parameter Name is required.')
  
          if not self.events_backend.enable_rule(name):
              return self.error('ResourceNotFoundException', 'Rule ' + name + ' does not exist.')
  
          return '', self.response_headers
  
      def generate_presigned_url(self):
          pass
  
      def list_rule_names_by_target(self):
          target_arn = self._get_param('TargetArn')
          next_token = self._get_param('NextToken')
          limit = self._get_param('Limit')
  
          if not target_arn:
              return self.error('ValidationException', 'Parameter TargetArn is required.')
  
          rule_names = self.events_backend.list_rule_names_by_target(
              target_arn, next_token, limit)
  
          return json.dumps(rule_names), self.response_headers
  
      def list_rules(self):
          prefix = self._get_param('NamePrefix')
          next_token = self._get_param('NextToken')
          limit = self._get_param('Limit')
  
          rules = self.events_backend.list_rules(prefix, next_token, limit)
          rules_obj = {'Rules': []}
  
          for rule in rules['Rules']:
              rules_obj['Rules'].append(self._generate_rule_dict(rule))
  
          if rules.get('NextToken'):
              rules_obj['NextToken'] = rules['NextToken']
  
          return json.dumps(rules_obj), self.response_headers
  
      def list_targets_by_rule(self):
          rule_name = self._get_param('Rule')
          next_token = self._get_param('NextToken')
          limit = self._get_param('Limit')
  
          if not rule_name:
              return self.error('ValidationException', 'Parameter Rule is required.')
  
          try:
              targets = self.events_backend.list_targets_by_rule(
                  rule_name, next_token, limit)
          except KeyError:
              return self.error('ResourceNotFoundException', 'Rule ' + rule_name + ' does not exist.')
  
          return json.dumps(targets), self.response_headers
  
      def put_events(self):
          events = self._get_param('Entries')
  
          failed_entries = self.events_backend.put_events(events)
  
          if failed_entries:
              return json.dumps({
                  'FailedEntryCount': len(failed_entries),
                  'Entries': failed_entries
              })
  
          return '', self.response_headers
  
      def put_rule(self):
          name = self._get_param('Name')
          event_pattern = self._get_param('EventPattern')
          sched_exp = self._get_param('ScheduleExpression')
          state = self._get_param('State')
          desc = self._get_param('Description')
          role_arn = self._get_param('RoleArn')
  
          if not name:
              return self.error('ValidationException', 'Parameter Name is required.')
  
          if event_pattern:
              try:
                  json.loads(event_pattern)
              except ValueError:
                  # Not quite as informative as the real error, but it'll work
                  # for now.
                  return self.error('InvalidEventPatternException', 'Event pattern is not valid.')
  
          if sched_exp:
              if not (re.match('^cron\(.*\)', sched_exp) or
                      re.match('^rate\(\d*\s(minute|minutes|hour|hours|day|days)\)', sched_exp)):
                  return self.error('ValidationException', 'Parameter ScheduleExpression is not valid.')
  
          rule_arn = self.events_backend.put_rule(
              name,
              ScheduleExpression=sched_exp,
              EventPattern=event_pattern,
              State=state,
              Description=desc,
              RoleArn=role_arn
          )
  
          return json.dumps({'RuleArn': rule_arn}), self.response_headers
  
      def put_targets(self):
          rule_name = self._get_param('Rule')
          targets = self._get_param('Targets')
  
          if not rule_name:
              return self.error('ValidationException', 'Parameter Rule is required.')
  
          if not targets:
              return self.error('ValidationException', 'Parameter Targets is required.')
  
          if not self.events_backend.put_targets(rule_name, targets):
              return self.error('ResourceNotFoundException', 'Rule ' + rule_name + ' does not exist.')
  
          return '', self.response_headers
  
      def remove_targets(self):
          rule_name = self._get_param('Rule')
          ids = self._get_param('Ids')
  
          if not rule_name:
              return self.error('ValidationException', 'Parameter Rule is required.')
  
          if not ids:
              return self.error('ValidationException', 'Parameter Ids is required.')
  
          if not self.events_backend.remove_targets(rule_name, ids):
              return self.error('ResourceNotFoundException', 'Rule ' + rule_name + ' does not exist.')
  
          return '', self.response_headers
  
      def test_event_pattern(self):
          pass
  
      def put_permission(self):
          action = self._get_param('Action')
          principal = self._get_param('Principal')
          statement_id = self._get_param('StatementId')
  
          self.events_backend.put_permission(action, principal, statement_id)
  
          return ''
  
      def remove_permission(self):
          statement_id = self._get_param('StatementId')
  
          self.events_backend.remove_permission(statement_id)
  
          return ''
  
      def describe_event_bus(self):
          return json.dumps(self.events_backend.describe_event_bus())
  