/* eslint no-fallthrough: 0 */
import moment from 'moment';
import dateMath from './date-arithmetic';
// import localizer from '../localizer'; 
 
const MILLI = {
  seconds: 1000,
  minutes: 1000 * 60,
  hours: 1000 * 60 * 60,
  day: 1000 * 60 * 60 * 24
}


let directions = {
  LEFT:  'LEFT',
  RIGHT: 'RIGHT',
  UP:    'UP',
  DOWN:  'DOWN'
} 

let dates = Object.assign(dateMath, {

  monthsInYear(year){
    let months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
      , date = new Date(year, 0, 1)

    return months.map(i => dates.month(date, i))
  },

  firstVisibleDay(date, culture){
    let firstOfMonth = dates.startOf(date, 'month')

    return dates.startOf(firstOfMonth, 'week', 0);
  },

  lastVisibleDay(date, culture){
    let endOfMonth = dates.endOf(date, 'month')

    return dates.endOf(endOfMonth, 'week', 0);
  },

  visibleDays(date, culture){
    let current = dates.firstVisibleDay(date, culture)
      , last = dates.lastVisibleDay(date, culture)
      , days = [];

    while (dates.lte(current, last, 'day')) {
      days.push(current)
      current = dates.add(current, 1, 'day')
    }

    return days
  },
  firstWeekOfVisibleDay(date){
    let firstOfMonth = dates.startOf(date, 'week');
    return dates.startOf(firstOfMonth, 'week', 0);
  },
  lastWeekOfVisibleDay(date){
    let endOfMonth = dates.endOf(date, 'week') 
    return dates.endOf(endOfMonth, 'week', 0);
  },
  visibleRangeDays(start,end, culture){
    let current = dates.firstWeekOfVisibleDay(start, culture)
      , last = dates.lastWeekOfVisibleDay(end, culture)
      , days = [];  
    while (dates.lte(current, last, 'day')) {
      days.push(current)
      current = dates.add(current, 1, 'day')
    }

    return days
  },

  ceil(date, unit){
    let floor = dates.startOf(date, unit)

    return dates.eq(floor, date) ? floor : dates.add(floor, 1, unit)
  },

  move(date, min, max, unit, direction){
    let isUpOrDown = direction === directions.UP || direction === directions.DOWN
      , addUnit = isUpOrDown ? 'week' : 'day'
      , amount = isUpOrDown ? 4 : 1
      , newDate;

    if (direction === directions.UP || direction === directions.LEFT)
      amount *= -1

    newDate = dates.add(date, amount, addUnit)

    return dates.inRange(newDate, min, max, 'day')
      ? newDate
      : date
  },

  range(start, end, unit = 'day'){
    let current = start
      , days = [];

    while (dates.lte(current, end, unit)) {
      days.push(current)
      current = dates.add(current, 1, unit)
    }

    return days
  },

  merge(date, time){
    if( time == null && date == null)
      return null

    if (time == null) time = new Date()
    if (date == null) date = new Date()

    date = dates.startOf(date, 'day')
    date = dates.hours(date,        dates.hours(time))
    date = dates.minutes(date,      dates.minutes(time))
    date = dates.seconds(date,      dates.seconds(time))
    return dates.milliseconds(date, dates.milliseconds(time))
  },

  sameMonth(dateA, dateB){
    return dates.eq(dateA, dateB, 'month')
  },
  sameDay(dateA, dateB){
    return dates.eq(dateA, dateB, 'day')
  },
  eqTime(dateA, dateB){
    return dates.hours(dateA) === dates.hours(dateB)
      && dates.minutes(dateA) === dates.minutes(dateB)
      && dates.seconds(dateA) === dates.seconds(dateB)
  },

  isJustDate(date){
    return (
         dates.hours(date) === 0
      && dates.minutes(date) === 0
      && dates.seconds(date) === 0
      && dates.milliseconds(date) === 0
    )
  },

  duration(start, end, unit, firstOfWeek){
    if (unit === 'day') unit = 'date';
    return Math.abs(dates[unit](start, undefined, firstOfWeek) - dates[unit](end, undefined, firstOfWeek))
  },

  diff(dateA, dateB, unit){
    if (!unit)
      return Math.abs(+dateA - +dateB) 
    return Math.abs(
      (+dates.startOf(dateA, unit) / MILLI[unit]) - (+dates.startOf(dateB, unit) / MILLI[unit])
    )
  },

  diffTime(timeA,timeB,unit){  
    return ((dates.startOf('1990-01-01 '+timeB, unit) / MILLI[unit])-(dates.startOf('1990-01-01 '+timeA, unit) / MILLI[unit]));
  },
  total(date, unit) {
    let ms = date.getTime()
      , div = 1;

    switch (unit) {
      case 'week':
        div *= 7
      case 'day':
        div *= 24
      case 'hours':
        div *= 60
      case 'minutes':
        div *= 60
      case 'seconds':
        div *= 1000;
    }

    return ms / div;
  },

  week(date){
    var d = new Date(date);
    d.setHours(0, 0, 0);
    d.setDate(d.getDate() + 4 - (d.getDay() || 7));
    return Math.ceil((((d - new Date(d.getFullYear(), 0, 1)) / 8.64e7 ) + 1) / 7);
  },

  today() {
    return dates.startOf(new Date(), 'day')
  },

  yesterday() {
    return dates.add(dates.startOf(new Date(), 'day'), -1, 'day')
  },

  tomorrow() {
    return dates.add(dates.startOf(new Date(), 'day'), 1, 'day')
  }
})

export default dates;