text: '''
  Interactions for and within a lesson.
  '''
  import os
  import pandas as pd
  import shutil
  import sys
  from colorama import Fore, Back, Style
  from dojo import ROOT_DIR, LESSONS_DIR, TRAINING_FEEDSTOCKS_DIR
  from dojo.utils import add_lesson_yaml, download_package, get_latest, \
      update_history, create_lesson_progress, get_all_lesson_progress, \
      get_lesson_progress, get_timestamp_for_file, \
      load_lesson_specs, update_lesson_progress
  from git import Repo
  
  
  def clean_dojo_channels(lesson_name):
      # If dojo_channels directory exists, delete it.
      dojo_channels_path = os.path.join(LESSONS_DIR, lesson_name, 'dojo_channels')
      if os.path.isdir(dojo_channels_path):
          print('Removing dojo_channels directory...')
          shutil.rmtree(dojo_channels_path)
          print('...success!')
  
  
  def clean_history_and_progress():
      '''
      Deletes history.csv and progress.csv files.
      '''
      while True:
          user_response = str(input(Fore.RED + f'CONFIRM: Are you sure you want to delete ALL of your history and progress files? (y/n) '))
          print(Style.RESET_ALL)
          if user_response.lower() not in ['y', 'n']:
              print('Sorry, I did not understand.')
          else:
              break
  
      if user_response.lower() == 'y':
          history_path = os.path.join(ROOT_DIR, 'history.csv')
          if os.path.exists(history_path):
              os.remove(history_path)
          
          from glob import glob
          all_lesson_dirs = glob(os.path.join(LESSONS_DIR,'*'))
          for lesson_dir in all_lesson_dirs:
              progress_path = os.path.join(lesson_dir, 'progress.csv')
              if os.path.exists(progress_path):
                  os.remove(progress_path)
          
          print('Done. All history and progress files have been deleted.')
  
      elif user_response.lower() == 'n':
          sys.exit(0)
  
  def clone_checkout_feedstock(feedstock_url, commit):
      '''
      Clones the lesson's feedstock and checks
      out the specified commmit.
      '''
      print('\nSetting up feedstock snapshot...')
      repo_name = get_repo_name(feedstock_url)
      os.chdir(TRAINING_FEEDSTOCKS_DIR)
  
      print(f'Cloning {repo_name} at {commit}')
      clone_target_path = os.path.join(TRAINING_FEEDSTOCKS_DIR, repo_name)
  
      # Clone feedstock
      if os.path.isdir(clone_target_path):
          shutil.rmtree(clone_target_path)
      repo = Repo.clone_from(feedstock_url, clone_target_path)
  
      # Checkout commit
      repo.git.checkout(commit)
  
      os.chdir(ROOT_DIR)
      print('...successfully set up feedstock snapshot!')
  
      return clone_target_path
  
  
  def create_lesson(new_lesson_name, target_platform):
      '''
      Creates a lesson directory and a lesson.yaml.
      '''
      subdirs = ['noarch', target_platform]
  
      # Create lesson directory (increments from the last lesson's number).
      last_lesson_number = get_last_lesson_number()
      new_lesson_number_str = str(last_lesson_number + 1)
      new_lesson_number_str = new_lesson_number_str.zfill(3)
      new_lesson_folder = f'{new_lesson_number_str}_{new_lesson_name}'
      new_lesson_path = os.path.join(LESSONS_DIR, new_lesson_folder)
      os.mkdir(new_lesson_path)
  
      # Add a lesson.yaml (will need to be edited by the lesson creator).
      add_lesson_yaml(new_lesson_path)
  
      # Show info about where to find the new directory and next steps.
      print(f'New lesson created at: {new_lesson_path}')
      print('In this directory, you will find the "lesson.yaml". Please add your lesson content in this file.')
  
  
  def display_prompt(lesson_name, lesson_specs, step_index, verbose=False):
      '''
      Displays the lesson name and step info, and (if specified) additional
      details about the lesson.
      Also shows any notes entered for the step.
      '''
      if verbose:
          details = '  Objectives:'
          for obj in lesson_specs['objectives']:
              details += f'\n    - {obj}'
          repo_name = get_repo_name(lesson_specs['feedstock_url'])
          recipe_path = os.path.join(TRAINING_FEEDSTOCKS_DIR, repo_name, 'recipe')
          details += f'\n  Recipe path: {recipe_path}'
      else:
          details = None
  
      # Step prompt.
      total_num_prompts = len(lesson_specs['prompts'])
      prompt_location = f'{step_index + 1} of {total_num_prompts}'
      prompt = lesson_specs['prompts'][step_index]
  
      # Get any notes that exist for current step_index.
      df_progress = get_all_lesson_progress(lesson_name)
      df_rows_with_notes = df_progress[(df_progress['lesson_index']==step_index) & (df_progress.note.notnull())]
      rows_with_notes = df_rows_with_notes.values.tolist()
      
      if rows_with_notes:
          notes = '\n  My notes:'
          for note in rows_with_notes:
              date = note[1].split(' ')[0]
              content = note[3]
              notes += f'\n    - ({date}) {content}'
      else: 
          notes = None
  
      print(Fore.CYAN + '\n=============================== CONDA-BUILD DOJO ===============================')
      print('||                                                                            ||')
      print(f'\n  Lesson: "{lesson_specs["title"]}"')
      if details:
          print(details)
      print(f'\n  Step {prompt_location}')
      print(f'\n{prompt}')
      if notes:
          print(notes)
      print('\n||                                                                            ||')
      print('================================================================================')
      print(f' OPTIONS: dojo (p)revious; (c)urrent; (n)ext; (j)ump; (a)dd note; (stop) lesson.\n')
      print(Style.RESET_ALL)
  
  
  def get_last_lesson_number():
      '''
      Gets the number of the last created lesson (e.g. 001).
      To be used when running 'dojo create_lesson'.
      '''
      from glob import glob
      all_lesson_dirs = glob(os.path.join(LESSONS_DIR,'*'))
      return max([int(n.split('/')[-1].split('_')[0]) for n in all_lesson_dirs])
  
  
  def get_repo_name(feedstock_url):
      '''
      Parses the repo name from the feedstock URL.
      '''
      return feedstock_url.split('/')[-1].split('.git')[0]
  
  
  def setup_feedstock_and_condarc(lesson_name):
      lesson_specs = load_lesson_specs(lesson_name)
      feedstock_url = lesson_specs['feedstock_url']
      commit = lesson_specs['commit']
  
      # Clone feedstock and checkout to specifiec commit.
      clone_checkout_feedstock(feedstock_url, commit)
  
      # Set up dojo_channels (only if "dojo_channels_pkgs.txt" file exists and it's not empty):
      dojo_channels_pkgs = os.path.join(LESSONS_DIR, lesson_name, 'dojo_channels_pkgs.txt')
      if os.path.exists(dojo_channels_pkgs) and os.stat(dojo_channels_pkgs).st_size > 0:
          print('\nSetting up dojo_channels...')
  
          # Parse each URL to get its channel, subdir, and filename. For example: 
          # {
          #  'https://repo.anaconda.com/pkgs/main/linux-64/python-3.9.2-hdb3f193_0.conda': 
          #     {
          #      'channel': 'main', 
          #      'subdir' : 'linux-64',
          #      'fn' : 'python-3.9.2-hdb3f193_0.conda'
          #     }
          # }
          url_parsed_dict = {}
          
          with open(dojo_channels_pkgs, 'r') as url_list:
              urls = url_list.read().splitlines()
              for url in urls:
                  
                  channel = url.split('/')[-3]
                  subdir = url.split('/')[-2]
                  fn = url.split('/')[-1]
                  url_parsed_dict[url] = {'channel': channel, 'subdir': subdir, 'fn': fn}
  
          # Download each URL to the appropriate destination path.
          for pkg_url, url_parts in url_parsed_dict.items():
              destination_path = os.path.join(LESSONS_DIR, 
                                              lesson_name, 
                                              'dojo_channels', 
                                              url_parts['channel'], 
                                              url_parts['subdir'], 
                                              url_parts['fn'])
              download_package(pkg_url, destination_path)
  
          # Run `conda index` on each dojo channel.
          from glob import glob
          dojo_channels = glob(os.path.join(LESSONS_DIR,lesson_name, 'dojo_channels', '*'))
          for dojo_channel_path in dojo_channels:
              import subprocess
              print(f'Running "conda index" on {dojo_channel_path}')
              subprocess.run(['conda', 'index', dojo_channel_path])
  
          # If a .condarc exists, back it up.
          home_path = os.environ['HOME']
          condarc_path = os.path.join(home_path, '.condarc')
          if os.path.exists(condarc_path):
              ts = get_timestamp_for_file()
              renamed_condarc_path = os.path.join(home_path, f'.condarc_bak_{ts}')
              os.rename(condarc_path, renamed_condarc_path)
              print('Found an existing .condarc file.')
              print(f'Backing it up to: {renamed_condarc_path}')
  
          # Create a .condarc that points to the lesson's dojo_channels.
          with open(condarc_path, 'w') as new_condarc:
              new_condarc.write('channels: \n')  # Must have a space after the colon. See: https://stackoverflow.com/a/9055411
              for channel in dojo_channels:
                  new_condarc.write(f'  - {channel}\n')
  
          print('...successfully set up dojo_channels!')
  
  
  def start(lesson_name):
      '''
      Starts a new lesson by setting up the feedstock and condarc.
      Also checks if a user already started the specified lesson 
      and handles accordingly.
      '''
      lesson_specs = load_lesson_specs(lesson_name)
      feedstock_url = lesson_specs['feedstock_url']
      commit = lesson_specs['commit']
  
      # Check whether a progress.csv already exists (which would mean
      # they've started this lesson before). 
      # If so, ask whether they want to resume, start over, or cancel.
      if os.path.exists(os.path.join(LESSONS_DIR, lesson_name, 'progress.csv')):
          while True:
              user_response = str(input(f'You previously started "{lesson_name}". \nDo you wish to (r)esume, (s)tart over, or (c)ancel? '))
              if user_response.lower() not in ['c', 's']:
                  print('Sorry, I did not understand.')
              else:
                  break
          if user_response.lower() == 'r':  # Resume
              setup_feedstock_and_condarc(lesson_name)
              update_history(lesson_name, 'resume')
              step_current(verbose=True)
          elif user_response.lower() == 's':  # Start over
              setup_feedstock_and_condarc(lesson_name)
              update_history(lesson_name, 'start over')
              update_lesson_progress(lesson_name, 0)
              step_current(verbose=True)
          elif user_response.lower() == 'c':  # Cancel
              sys.exit(0)
  
      else:
          setup_feedstock_and_condarc(lesson_name)
          update_history(lesson_name, 'start')
          create_lesson_progress(lesson_name)
          display_prompt(lesson_name, lesson_specs, 0, verbose=True)
  
  
  def step_previous(verbose=False):
      '''
      Show the previous step.
      '''
      lesson_name, current_step_index = get_latest()
      if current_step_index > 0:
          new_step_index = current_step_index - 1
      else:
          new_step_index = 0
      lesson_specs = load_lesson_specs(lesson_name)
  
      update_lesson_progress(lesson_name, new_step_index)
      display_prompt(lesson_name, lesson_specs, new_step_index, verbose=verbose)
  
  
  def step_current(verbose=False):
      '''
      Show the current step.
      '''
      lesson_name, current_step_index = get_latest()
      lesson_specs = load_lesson_specs(lesson_name)
      display_prompt(lesson_name, lesson_specs, current_step_index, verbose=verbose)
  
  
  def step_next(verbose=False):
      '''
      Show the next step.
      If at the end, the next step is a congratulatory message
      and advice on what to do now.
      '''
      lesson_name, current_step_index = get_latest()
      lesson_specs = load_lesson_specs(lesson_name)
      max_step_index = len(lesson_specs['prompts']) - 1
  
      if current_step_index == max_step_index:
          # There are no more steps, so the lesson is done.
          lesson_title = lesson_specs['title']
          update_history(lesson_name, 'completed')
          # print()
          print(Fore.BLACK + Back.YELLOW + '')
          print(f'\n + + + + Congrats! You have completed "{lesson_title}". + + + +')
          print(f'\n You should now be able to:')
          for obj in lesson_specs['objectives']:
              print(f'   - {obj}')
          print('\n You can review this lesson (and any notes you added) by re-starting the lesson.')
          print(' Otherwise, onward and upward to a new lesson!')
          print(Style.RESET_ALL)
          stop(completed_lesson_name=lesson_name)
          sys.exit(0)
  
      new_step_index = current_step_index + 1
      update_lesson_progress(lesson_name, new_step_index)
      display_prompt(lesson_name, lesson_specs, new_step_index, verbose=verbose)
  
  
  def step_jump(step_number, verbose=False):
      '''
      Jump to a specified step number.
      '''
      lesson_name, current_step_index = get_latest()
      lesson_specs = load_lesson_specs(lesson_name)
      max_step_number = len(lesson_specs['prompts'])
  
      if (int(step_number) > max_step_number) or (int(step_number) < 1):
          print('ERROR: That step number does not exist.')
          sys.exit(1)
  
      new_step_index = int(step_number) - 1
      update_lesson_progress(lesson_name, new_step_index)
      display_prompt(lesson_name, lesson_specs, new_step_index, verbose=verbose)
  
  
  def step_add_note():
      '''
      Add a note to current step_index in the progress.csv
      '''
      lesson_name, current_step_index = get_latest()
      lesson_specs = load_lesson_specs(lesson_name)
  
      # Get note from the user.
      note = str(input('Please enter your note: '))
  
      # Record note in progress.csv.
      update_lesson_progress(lesson_name, current_step_index, note=note)
  
      # Display the current step with the new note.
      display_prompt(lesson_name, lesson_specs, current_step_index)
  
      print(f'Added note to {os.path.join(LESSONS_DIR, lesson_name, "progress.csv")}')
      print('To edit or delete the note, please do so in the csv file itself.')
  
  
  def stop(completed_lesson_name=None):
      '''
      Stop the lesson and clean up its dojo_channels dir (if it exists).
      '''
      if completed_lesson_name:
          clean_dojo_channels(completed_lesson_name)
  
      else:  # User is stopping the lesson before finishing it.
          lesson_name, _ = get_latest()
          update_history(lesson_name, 'stop')
          clean_dojo_channels(lesson_name)
          print(f'Stopped lesson: {lesson_name}')
  
  