    init = (jQuery) ->
      window['edu.goshen.library'] = {};

Require `papaparse` before running the code to fetch reserves, ebooks, and
libguides.

      require([
        'https://unpkg.com/papaparse@^5.3.0'
      ], (Papa) ->
        {department, course, labUnit, section, prettySemester, year} = getDepartmentAndCourse()

        getReservesAndEbooks(Papa, department, course, labUnit, section, prettySemester, year)
        getLibraryGuideLinkInformation(Papa, department, course, prettySemester, year)
      )

This section selects an image randomly from a pool and puts it before the
`reactive-block` so that it sits at the top of the Moodle block.

      images = [
        'https://libraryapps.goshen.edu/resources/images/search_background/browsing_stacks.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/entrance_north.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/entrance_south.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/group_study.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/homepage_hours.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/library_blooms.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/periodicals.jpg'
        'https://libraryapps.goshen.edu/resources/images/search_background/soft_seating.jpg'
      ]

      headerImage = jQuery('<img>')
        .css('width', '100%')
        .attr('src', images[Math.floor(Math.random() * images.length)])
        .attr('alt', 'Good Library, Goshen College')

      jQuery('#reactive-block-container').before(jQuery('<div>').append(headerImage).css('margin-bottom', '1em'))

    getDepartmentAndCourse = () ->
      # We should get the department and course.

      title = document.querySelector('#page-header h1').textContent or ''

      courseCode = title.split(':', 1)[0]

      courseCodeUnits = courseCode.match(///^
        (\w{3,4})       # Department code.
        (\d{3})         # Course number.
        (?:-(L))?       # Lab unit. (optional)
        (?:-(\d{2}))?   # Section. (optional)
        (?:-(\w{2}))?   # Perspective or location. [Location can be 'ML' (Merry Lea), 'EL' (Elkhart), 'GL' (Glen Oaks).] [Can we ever have both?] (optional)
        -(\w{2}|\d{2})  # Semester (letters) or nursing cohort (number).
        (\d{4})         # Year.
      ///)

      courseInformation = {}

      if courseCodeUnits?
        courseInformation.department = courseCodeUnits[1].toLowerCase() if courseCodeUnits[1]?
        courseInformation.course = courseCodeUnits[2] if courseCodeUnits[2]?
        courseInformation.labUnit = courseCodeUnits[3]?
        courseInformation.section = courseCodeUnits[4] if courseCodeUnits[4]?

        if courseCodeUnits[5]?
          [courseInformation.location, courseInformation.prettyLocation] = switch courseCodeUnits[5]
            when 'ML' then ['ML', 'Merry Lea']
            when 'EL' then ['EL', 'Elkhart']
            when 'GL' then ['GL', 'Glen Oaks']
            else [undefined, undefined]

          [courseInformation.perspective, courseInformation.prettyPerspective] = switch courseCodeUnits[5]
            when 'RW' then ['RW', 'Religious World']
            when 'SW' then ['SW', 'Social World']
            when 'NW' then ['NW', 'Natural World']
            when 'AW' then ['AW', 'Artistic World']
            when 'PX' then ['PX', 'Peacemaking']
            else [undefined, undefined]
        else
          courseInformation.location = courseInformation.prettyLocation = courseInformation.perspective = courseInformation.prettyPerspective = undefined

        if courseCodeUnits[6]? and courseCodeUnits[6]
          courseInformation.nursingCohort = Number.parseInt(courseCodeUnits[6]) if Number.parseInt(courseCodeUnits[6])
          [courseInformation.semester, courseInformation.prettySemester] = if not Number.parseInt(courseCodeUnits[6]) then switch courseCodeUnits[6]
            when 'FA' then ['FA', 'Fall']
            when 'SP' then ['SP', 'Spring']
            when 'MA' then ['MA', 'May Term']
            when 'SU' then ['SU', 'Summer']
            else [undefined, undefined]
        else
          courseInformation.nursingCohort = courseInformation.semester = courseInformation.prettySemester = undefined

        courseInformation.year = courseCodeUnits[7] if courseCodeUnits[7]?

      console.log(courseInformation)

      return courseInformation

    getReservesAndEbooks = (Papa, department, course, labUnit, section, semester, year) ->
      Papa.parse(
        'https://docs.google.com/spreadsheets/d/e/2PACX-1vTasyDNyksC4g6-FM_H3jdqSZQMuSxr-9rPbvFViiLCU_ZQ8EFM19oTJw6TSCrb-SivRwWReJ2RIeSI/pub?gid=0&single=true&output=csv'
          download: true
          header: true
          complete: (results) ->
            books = results.data
            
            console.log(books)

This is where we would want to test for lab or section.

            if labUnit
              books = (book for book in books when book.Lab is 'Yes')
            else
              books = (book for book in books when book.Lab isnt 'Yes')

            if section
              books = (book for book in books when (book.Section is section or book.Section is ''))

            courseBooks = ({ title: book.Title, oclcnum: book['OCLC Number'], href: book.Url } for book in books when book.Department is department and book.Course is course and book.Semester is semester and book.Year is year)

            console.log(courseBooks)

eBooks come before reserves. (They are actionable _right now_, so they are more
important.)

            makeList(courseBooks.filter((book) ->
              return book.href
            ), 'eBook Textbooks', makeBook)

            makeList(courseBooks.filter((book) ->
              return not book.href
            ), 'Textbooks on reserve at Library Front Desk (2-hour Checkout)', makeBook)
            
            queryCarp()
      )

    getLibraryGuideLinkInformation = (Papa, department, course) ->
      Papa.parse(
        'https://docs.google.com/spreadsheets/d/e/2PACX-1vTasyDNyksC4g6-FM_H3jdqSZQMuSxr-9rPbvFViiLCU_ZQ8EFM19oTJw6TSCrb-SivRwWReJ2RIeSI/pub?gid=508368187&single=true&output=csv'
          download: true
          header: true
          complete: (results) ->
            links = results.data
            
            console.log(links)

            courseLinks = ({ name: link.Name, href: link.Url, title: link.title } for link in links when link.Department is department and link.Course is course)

            console.log(courseLinks)

            makeList(courseLinks, 'Library Guides', makeLink)
      )

    makeList = (elements, listTitle, elementMaker) ->

Only do anything if there are links.

      return if not elements.length > 0

First make the title.

      title = document.createElement('p')
      title.appendChild(document.createTextNode(listTitle))
      title.setAttribute('style', 'font-weight: bold')

      document.getElementById('reactive-block-container').appendChild(title)

Now make the link list.

      list = document.createElement('ul')
      list.className = 'reactive-block-list'
      list.setAttribute('style', 'margin-left: 0; list-style: none')

      for element in elements
        elementMaker(list, element)

      document.getElementById('reactive-block-container').appendChild(list)

    makeBook = (list, book) ->
      return if not book.title

Making an entry for a book is a little more complicated than making a simple
link, because we can either be listing a book on reserve or linking to an ebook.

We can tell the difference, because ebooks have `href` set.

      if book.href
        bookElement = makeEbook(book)
      else
        bookElement = makeReserveBook(book)

      if bookElement
        listItem = document.createElement('li')
        listItem.setAttribute('style', 'margin-bottom: 10px;')

        listItem.appendChild(bookElement)

        list.appendChild(listItem)

This function is used by `makeBook` to make the elements for an ebook entry.

    makeEbook = (book) ->
      console.log(window['edu.goshen.library'].p)

      return if not book.title or not book.href

      container = document.createDocumentFragment()

      bookElement = document.createElement('a')
      bookElement.appendChild(document.createTextNode(book.title))
      bookElement.setAttribute('href', book.href)
      bookElement.setAttribute('target', '_blank')
      bookElement.setAttribute('style', 'font-style: italic;')

      container.appendChild(bookElement)

      availabilityElement = document.createElement('span')
      availabilityElement.className = 'availability'
      availabilityElement.setAttribute('style', 'display: block;')

      availabilityIndicator = document.createElement('span')
      availabilityIndicator.className = 'availability-indicator'
      availabilityIndicator.setAttribute('style', 'display: inline-block; height: 1em; width: 1em; border-radius: 50%; vertical-align: middle; background-color: #5cb85c')

      availabilityText = document.createElement('span')
      availabilityText.setAttribute('style', 'vertical-align: middle')
      availabilityText.appendChild(document.createTextNode('\xa0Available online'))

      availabilityElement.appendChild(availabilityIndicator)
      availabilityElement.appendChild(document.createTextNode('\xa0'))
      availabilityElement.appendChild(availabilityText)

      container.appendChild(availabilityElement)

      return container

This function is used by `makeBook` to make the elements for a reserve entry.

    makeReserveBook = (book) ->
      return if not book.title

      bookElement = document.createElement('span')
      bookElement.appendChild(document.createTextNode(book.title))
      bookElement.setAttribute('style', 'font-style: italic;')

      if book.oclcnum
        bookElement.setAttribute('data-oclcnum', book.oclcnum)

      return bookElement

    makeLink = (list, link) ->
      return if not link.name

      linkElement = if link.href? then document.createElement('a') else document.createElement('span')
      linkElement.appendChild(document.createTextNode(link.name))
      linkElement.setAttribute('href', link.href) if link.href?
      linkElement.setAttribute('title', link.title) if link.title?
      linkElement.setAttribute('target', '_blank')

      listItem = document.createElement('li')

      listItem.appendChild(linkElement)

      list.appendChild(listItem)

This function looks for elements with `data-oclcnum`, sends the number off to
the `resources/apps/carp` service and adds an element which indicates whether
the associated item is available.

    queryCarp = () ->
      require([
        'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.12/handlebars.runtime.min.js'
      ], (moment, Handlebars) ->

Get all the 'templatey' stuff ready here; no need to put it through all the loops.

        availabilityStrings =
          available:
            true: '\xa0available for checkout'
            false: 'Available for checkout'
          'checked-out':
            true: '\xa0checked out'
            false: 'Checked out'
          due:
            true: '\xa0due\xa0'
            false: 'Due\xa0'

        availabilityElement = $('<span>').addClass('availability').css({
          display: 'block'
        })

        availabilityIndicator = $('<span>').addClass('availability-indicator').css({
          display: 'inline-block'
          height: '1em'
          width: '1em'
          'border-radius': '50%'
          'vertical-align': 'middle'
        })

        availabilityText = $('<span>').addClass('availability-text').css('vertical-align', 'middle')

        availabilityElement.append(availabilityIndicator)
        availabilityElement.append(document.createTextNode('\xa0'))
        availabilityElement.append(availabilityText)

        $('*[data-oclcnum]').each((index, element) ->
          oclcnum = $(element).attr('data-oclcnum')

          $.getJSON('https://libraryapps.goshen.edu/resources/apps/carp/index.php', {
            oclcNum: oclcnum
          })
          .done((data) ->
            displayAvailability = (item) ->
              thisAvailabilityElement = availabilityElement.clone()
              hasDesignator = item.designator isnt ''

              if item.availability.available is 1
                thisAvailabilityElement.addClass('is-available')
                thisAvailabilityElement.find('.availability-indicator').css('background-color', '#5cb85c')
                thisAvailabilityElement.find('.availability-text').text(item.designator + availabilityStrings['available'][hasDesignator])
              else if item.availability.available is 0
                if (item.availability.availabilityDate)
                  thisAvailabilityElement.find('.availability-text').text(item.designator + availabilityStrings['due'][hasDesignator] + moment(item.availability.availabilityDate).fromNow())
                else
                  thisAvailabilityElement.find('.availability-text').text(item.designator + availabilityStrings['checked-out'][hasDesignator])

                thisAvailabilityElement.addClass('isnt-available')

                thisAvailabilityElement.find('.availability-indicator').css('background-color', '#f0ad4e')

              $(element).after(thisAvailabilityElement)
              $(element).after(document.createTextNode('\x0a'))

            displayAvailability(item) for item in data by -1
          )
          .fail(() ->
            console.log(arguments)
          )
        )
      )

Listening for `DOMContentLoaded` is not ideal, but it seems like the least
invasive way to make sure we have RequireJS _and_ jQuery _and_ PapaParse _and_
moment.js at the moment our script runs.

    document.addEventListener('DOMContentLoaded', () ->
      if require
        require(['jquery'], init)
    );
