text: # -*- coding: utf-8 -*-
  # The main program
  import sys
  import logging
  import config
  import telebot
  from telebot import types
  from picturebot import PictureBot
  from grabber import PictureGrabber
  from telebot import apihelper
  
  
  log = logging.getLogger(f'logger.{__name__}')
  
  if config.PROXY:
      apihelper.proxy = {'https': config.PROXY}
  
  bot = telebot.TeleBot(config.TOKEN)
  
  try:
      db_manager = config.get_db_manager(config.DB_TYPE, config.DB_SETTINGS)
  except Exception as e:
      log.exception(f'Error when getting db manager: {type(e)} - {str(e)}')
      log.info('Shutdown the bot.')
      sys.exit(1)
  
  picture_bot = PictureBot(db_manager, bot)
  
  
  # Main commands
  @bot.message_handler(commands=['help'])
  def send_help(message):
      """Sends simple hint for using this bot."""
      bot.reply_to(message, f'Use /start to run editing the schedule or @{config.BOT_NAME} to send pic now!')
  
  
  @bot.message_handler(commands=['stop'])
  def stop_subscribe(message):
      """Stops schedule setting or stops sending images and deletes the schedule from the database."""
      if picture_bot.get_setup_schedule_state(message.chat.id):
          picture_bot.schedule_setup_state.pop(message.chat.id)
          bot.reply_to(message, 'Schedule setting was stopped.')
      else:
          bot.reply_to(message, 'Schedule was deleted.')
          picture_bot.delete_subscriber(message.chat.id)
  
  
  # =====================================================================================================================
  # Start schedule setting.
  # =====================================================================================================================
  @bot.message_handler(commands=['start'])
  def start_enter_schedule(message):
      """Schedule setting, step #1: enter the query."""
      if picture_bot.is_schedule_exist(message.chat.id):
          markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
          markup.row('Continue', 'Cancel')
          bot.send_message(message.chat.id, 'The schedule already exist and will be deleted! Continue?',
                           reply_markup=markup)
      else:
          bot.reply_to(message, "Let's start schedule setting! Enter your query or '/stop' to exit:")
          picture_bot.set_schedule_state(message, 'start')
  
  
  # =====================================================================================================================
  # If the schedule already exists
  @bot.message_handler(func=lambda message: message.text == 'Cancel')
  def cancel_setting(message):
      """Interrupt setting - it already exists."""
      bot.send_message(message.chat.id, 'Schedule setting was canceled')
      picture_bot.schedule_setup_state.pop(message.chat.id)
  
  
  @bot.message_handler(func=lambda message: message.text == 'Continue')
  def continue_setting(message):
      """Overrides schedule setting"""
      picture_bot.delete_subscriber(message.chat.id)
      bot.send_message(message.chat.id, "The old schedule was deleted. Let's start the new one! "
                                        "Enter your query or '/stop' to exit:")
      picture_bot.set_schedule_state(message, 'start')
  
  
  # =====================================================================================================================
  @bot.message_handler(func=lambda message: picture_bot.get_setup_schedule_state(message.chat.id) == 'start')
  def enter_query(message):
      """Schedule setting, step #2: saves the query and offers interval types."""
      markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
      markup.row('Random', 'Interval')
      bot.send_message(message.chat.id, 'Well done! Now select your schedule variant:', reply_markup=markup)
      picture_bot.set_schedule_state(message, 'setup')
  
  
  @bot.message_handler(func=lambda message: picture_bot.get_setup_schedule_state(message.chat.id) == 'setup')
  def enter_interval_type(message):
      """Schedule setting, step #3: specify interval types."""
      if message.text == 'Interval':
          markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
          markup.row('Second', 'Minute', 'Hour', 'Day')
          markup.row('Week', 'Monday', 'Tuesday', 'Wednesday')
          markup.row('Thursday', 'Friday', 'Saturday', 'Sunday')
          bot.send_message(message.chat.id, 'Select interval type:', reply_markup=markup)
          picture_bot.set_schedule_state(message, 'interval')
      else:
          if message.text == 'Random':
              bot.reply_to(message, f'Now you will receive pics with an interval '
                                    f'of {config.INTERVAL_START} to {config.INTERVAL_END} minutes.')
              picture_bot.set_schedule_state(message, 'random')
          else:
              markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
              markup.row('Random', 'Interval')
              bot.send_message(message.chat.id, 'Incorrect value! try again:', reply_markup=markup)
              picture_bot.set_schedule_state(message, 'setup')
  
  
  @bot.message_handler(func=lambda message: picture_bot.get_setup_schedule_state(message.chat.id) == 'interval')
  def enter_interval_value(message):
      """Schedule setting, step #4: specify interval types."""
      if message.text in PictureBot.countable_intervals:
          bot.reply_to(message, 'Enter the period value:')
  
          if message.text == 'Day':
              picture_bot.set_schedule_state(message, 'day_schedule')
          else:
              picture_bot.set_schedule_state(message, 'last')
      else:
          if message.text in PictureBot.days_of_week:
              bot.reply_to(message, 'Enter the time (HH:MM):')
              picture_bot.set_schedule_state(message, 'last')
          else:
              markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
              markup.row('Second', 'Minute', 'Hour', 'Day')
              markup.row('Week', 'Monday', 'Tuesday', 'Wednesday')
              markup.row('Thursday', 'Friday', 'Saturday', 'Sunday')
              bot.send_message(message.chat.id, "Didn't understand! try again:", reply_markup=markup)
              picture_bot.set_schedule_state(message, 'interval')
  
  
  @bot.message_handler(func=lambda message: picture_bot.get_setup_schedule_state(message.chat.id) == 'day_schedule')
  def enter_interval_value_day(message):
      """Schedule setting, step #5: enter interval values."""
      if not picture_bot.wrong_input(message):
          bot.reply_to(message, 'Enter the start time (HH:MM):')
          picture_bot.set_schedule_state(message, 'last')
      else:
          bot.reply_to(message, 'Incorrect value! Try again:')
  
  
  @bot.message_handler(func=lambda message: picture_bot.get_setup_schedule_state(message.chat.id) == 'last')
  def last_step(message):
      """Schedule setting, step #6: checks and saves the schedule."""
      if picture_bot.wrong_input(message):
          bot.reply_to(message, 'Incorrect value! Try again:')
      else:
          bot.reply_to(message, 'Schedule setting was completed successfully!')
          picture_bot.set_schedule_state(message, 'end')
  # =====================================================================================================================
  # End schedule setting.
  # =====================================================================================================================
  
  
  @bot.inline_handler(func=lambda query: len(query.query) is 0)
  def empty_query(query):
      """The handler for an empty inline query.
  
      Sends a hint how to use this bot in inline mode.
  
      """
      hint = 'Enter a pic query!'
      try:
          r = types.InlineQueryResultArticle(
              id='1',
              title="Bot 'Sudden cat!'",
              description=hint,
              input_message_content=types.InputTextMessageContent(
                  message_text="Don't know what to say...")
          )
          bot.answer_inline_query(query.id, [r])
      except Exception as err:
          log.exception(f'Error in empty inline handler: {type(err)} - {str(err)}')
  
  
  @bot.inline_handler(func=lambda query: len(query.query) > 0)
  def search_query(query):
      """The handler for an inline query.
  
      Enter your query and choose the image to sending.
  
      """
      url_list = PictureGrabber.get_inline_img_url(query.query.strip())
  
      if len(url_list) == 0:
          return
  
      result_list = []
  
      try:
          for pic_id, pic_url in enumerate(url_list):
              result_list.append(
                  types.InlineQueryResultPhoto(
                      id=pic_id,
                      photo_url=pic_url,
                      thumb_url=pic_url
                  )
              )
  
          bot.answer_inline_query(query.id, result_list)
  
      except Exception as err:
          log.exception(f'Error in inline handler: {type(err)} - {str(err)}')
  
  
  #######################################################################################################################
  if __name__ == '__main__':
  
      log.info('Starting bot...')
      picture_bot.start()
      log.info('Bot has started')
      bot.polling(none_stop=True)
  