import moment from 'moment';

function dateFromDate(date) {
  if(!date) {
    return moment();
  }

  if(typeof date === 'string') {
    let dateObj = new Date(date);
    if(dateObj.toString() === 'Invalid Date') {
      console.log('Invalid Date:', date);
      throw date;
    }
    return moment(dateObj);
  }

  if(typeof date === 'object') {
    if(moment.isMoment(date)) {
      return date;
    } else {
      return moment(date);
    }
  }

  throw new Error('Do not know how to handle this type:', typeof date);
}

function dayFromString(dayOfWeek) {
  if (typeof dayOfWeek === 'string'){
    const dow = dayOfWeek.toLowerCase().slice(0, 3);
    const weekDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
    const dayNumber = weekDays.indexOf(dow);
    if (dayNumber === -1) {
      throw new Error('Do not recognize this day: ', dayOfWeek);
    }
    return dayNumber;
  }
    return dayOfWeek;
}

// nth - value from 1 through 5 for the (say) 4th Friday
// dayOfWeek - 0 through 6 (Sun through Sat) or can be string (i.e 'monday')
// relevantDate - a date as a string or Date object or moment object
// Returns a moment date
export function nthDay(nth, dayOfWeek, relevantDate) {
  relevantDate = dateFromDate(relevantDate);
  const month = relevantDate.month();
  const year = relevantDate.year();

  var dow = dayFromString(dayOfWeek);

  let counter = nth - 1;
  let day = counter * 7 + 1;

  const date = moment([year, month, day]);
  date.subtract(1, 'day');
  while(counter !== nth) {
    date.add(1, 'day');
    if(date.day() === dow) {
      counter++;
    }
  }
  return date;
}

@@ -882,26 +882,24 @@
 Number;%0A  %7D%0A
-  
   return day
@@ -906,16 +906,16 @@
 OfWeek;%0A
+
 %7D%0A%0A// nt
@@ -966,16 +966,146 @@
  Friday%0A
+//   Negative numbers count backwards from the end of the month%0A//   (For example, the last Friday, or the second to last Sunday)%0A
 // dayOf
@@ -1163,11 +1163,12 @@
 ng (
-i.e
+e.g.
  'mo
@@ -1319,16 +1319,26 @@
 vantDate
+, afterDay
 ) %7B%0A  re
@@ -1451,16 +1451,485 @@
 .year();
+%0A  afterDay = afterDay %7C%7C 0;%0A%0A  if (nth %3C 0) %7B%0A    // nth-last day of the month%0A    const fourthDay = nthDay(4, dayOfWeek, relevantDate);%0A    let occurrences;%0A%0A    if (fourthDay.add(1, 'week').month() %3E month) %7B%0A      // It's a month with four of this day of the week%0A      occurrences = 4;%0A    %7D else %7B%0A      // It's a month with five of this day of the week%0A      occurrences = 5;%0A    %7D%0A    return nthDay(occurrences + 1 + nth, dayOfWeek, relevantDate, afterDay);%0A  %7D
 %0A%0A  var 
@@ -1986,16 +1986,16 @@
 th - 1;%0A
-
   let da
@@ -2013,16 +2013,27 @@
  * 7 + 1
+ + afterDay
 ;%0A%0A  con

Implement the features that the tests specified