text: """The Cat Herder server routing module.
  
  """
  
  from datetime import datetime
  import os
  
  from py.src.bottle import (
      abort,
      delete,
      get,
      post,
      put,
      request,
      run,
      static_file,
      view,
  )
  
  from py.src.model import (
      Game,
      Calendar,
      Participant,
      InvalidEventWeekStartException,
  )
  from py.src.store import (
      load_mailgun_credentials,
      load_data,
      write_data,
  )
  from py.src.message import (
      send_update_email,
  )
  
  EPOCH = datetime.utcnow().strftime('%Y%m%d%H%M')
  PROCESS_ID = os.getpid()
  
  
  @get('/static/<filename>')
  def static(filename):
      """Loads static files (e.g. CSS, Javascript).
  
      """
      return static_file(filename, root='static')
  
  
  @get('/')
  @view('directory')
  def index():
      return {
          "epoch": EPOCH,
          "games": [
              game
              for game in Game.get_all()
              if not game.hidden
          ],
      }
  
  
  def _game_view(game_id, week_id):
      if not Game.contains(game_id):
          abort(404, "No such event.")
      try:
          data = load_data(game_id, week_id)
      except InvalidEventWeekStartException:
          abort(400, "Start date must be a Monday")
      last_week_id = Calendar.last_week_id(week_id)
      next_week_id = Calendar.next_week_id(week_id)
      max_week_id = Calendar.next_week_id()
      return {
          "epoch": EPOCH,
          "data": data,
          "participants": data.participants + [Participant()],
          "today": Calendar.now(),
          "last_week_id": last_week_id if week_id > "20160808" else None,
          "next_week_id": next_week_id if next_week_id <= max_week_id else None,
          "next_game": Game.next(game_id),
      }
  
  
  @get('/<game_id>')
  @view('schedule')
  def game(game_id):
      """Loads the main page.
  
      This loads the current state of the schedule from the database, and adds a
      new participant for the current user.
      """
      week_id = Calendar.this_week_id()
      return _game_view(game_id, week_id)
  
  
  @get('/<game_id>/<week_id>')
  @view('schedule')
  def history(game_id, week_id):
      """Loads the main page.
  
      This loads the current state of the schedule from the database, and adds a
      new participant for the current user.
      """
      return _game_view(game_id, week_id)
  
  
  def _update(request, game_id, week_id, pid):
      data = request.json
      new_participant_name = data['new_name']
      event_ids = data['event_ids']
      week_data = load_data(game_id, week_id)
      is_new = week_data.upsert_participant(
          pid,
          new_participant_name,
          event_ids,
      )
      write_data(week_data)
      try:
          creds = load_mailgun_credentials()
          send_update_email(creds, week_data, new_participant_name, is_new)
      except Exception as e:
          print('there was an error sending update email:')
          print(e)
      return
  
  
  @post('/game/<game_id>/event/<week_id>/participant')
  def participant_post(game_id, week_id):
      return _update(request, game_id, week_id, None)
  
  
  @put('/game/<game_id>/event/<week_id>/participant/<pid>')
  def participant_put(game_id, week_id, pid):
      return _update(request, game_id, week_id, pid)
  
  
  @delete('/game/<game_id>/event/<week_id>/participant/<pid>')
  def delete(game_id, week_id, pid):
      week_data = load_data(game_id, week_id)
      week_data.delete_participant(pid)
      write_data(week_data)
      return
  
  
  @put('/game/<game_id>/event/<week_id>/chosen/<event_id>')
  def chosen(game_id, week_id, event_id):
      week_data = load_data(game_id, week_id)
      week_data.toggle_chosen(event_id)
      write_data(week_data)
      return
  
  
  def run_server():
      with open('temp/server.pid', 'wt') as f:
          f.write(str(PROCESS_ID))
      run(
          host='localhost',
          port=5800,
          # debug=True,
      )
  