text: const bel = require('bel')
  const csjs = require('csjs-inject')
  const { isToday, format, isPast, getDay, setMonth, getDate, getMonth, getYear, getDaysInMonth } = require('date-fns')
  const protocol_maker = require('protocol-maker')
  
  var id = 0
  
  module.exports = calendarDays
  
  function calendarDays(opts, parent_wire) {
  	const { name = 'calendar', month, days, year, status = 'cleared'} = opts
  	const current_state = {
  		name,
  		month: month,
  		days,
  		year: year,
  		status,
  		first: null,
  		second: null,
  	}
  
  	//protocol
  	const initial_contacts = { 'parent': parent_wire }
  	const contacts = protocol_maker('input-number', listen, initial_contacts)
  
    function listen (msg) {
  		const { head, refs, type, data, meta } = msg // receive msg
  		const [from, to] = head
  		console.log('Cal days', { type, name: contacts.by_address[from].name, msg, data })
  		// handlers
  		if (type === 'clear') return clearSelf()
  		if (type === 'selecting-second') return colorRange(0, current_state.first)
  		if (type === 'not-selecting-second') {}
  		if (type === 'first-selected-by-startcal') return setStatus('first-selected-by-startcal')
  		if (type === 'first-selected-by-endcal') return setStatus('first-selected-by-endcal')
  		if (type === 'second-selected') return setStatus('second-selected-by-other')
  		if (type === 'color-from-start') return colorRange(0, current_state.first)
  		if (type === 'color-to-end') return colorRange(current_state.first, days + 1)
  		if (type === 'change') return render_new_cal(data)
  		if (type === 'color-range-from-start') return 
  		if (type === 'color-range-to-end') return 
  
    }
  	
  	const el = document.createElement('div')
  	const calendar = makeDays(days)
  	let buttons = [...calendar.children]
  	calendar.onmousemove = onmousemove
  	calendar.onclick = onclick
  	calendar.onmouseleave = onmouseleave
  	calendar.onmouseenter = onmouseenter
  
  	document.body.onclick = clear_all
  
  	el.append(calendar)
  	const $parent = contacts.by_name['parent']
  
  	return el
  
  	// event handlers
  	function onmousemove (event) {
  		console.log('onmousemove - current status', name, current_state.status)
  		const btn = event.target
  		const num = parseInt(btn.dataset.num)
  		if (!num || btn.classList.contains(css["disabled-day"])) return
  		if (current_state.status === 'first-selected-by-self') return markRange(current_state.first, num)
  		if (current_state.status === 'first-selected-by-startcal') return markRange(0, num)
  		if (current_state.status === 'first-selected-by-endcal') return markRange(num, days + 1)
  	}
  	function onclick (event) {
  		event.stopPropagation()
  		const btn = event.target
  		const current = parseInt(btn.dataset.num)
  		if (!current || btn.classList.contains(css["disabled-day"])) return
  		console.log('onclick - current status', current_state.status, current )
  		if (current_state.status === 'cleared') return selectFirst(btn, current)
  		if (current_state.status === 'first-selected-by-self') return selectSecond(btn, current)
  		if (current_state.status === 'first-selected-by-startcal') return selectSecond(btn, current)
  		if (current_state.status === 'first-selected-by-endcal') return selectSecond(btn, current)
  		if (current_state.status === 'second-selected-by-self') return selectFirst(btn, current)
  		if (current_state.status === 'second-selected-by-other') return selectFirst(btn, current)
  }
  	function onmouseleave (event) {
  		console.log('onmouseleave - first selected', current_state.status)
  		if (current_state.status === 'first-selected-by-startcal') return clearSelf()
  		if (current_state.status === 'first-selected-by-endcal') return clearSelf()
  		current_state.second = void 0
  		if (current_state.status === 'first-selected-by-self') {
  			current_state.second = void 0
  			if (name === 'calendar1') return markRange(current_state.first, days + 1)
  			else if (name === 'calendar2') return markRange(0, current_state.first)
  		}
  	}
  	function onmouseenter (event) {
  		console.log('onmouseenter - first selected', current_state.status)
  		if (current_state.status === 'first-selected-by-startcal') return notifyOther()
  		if (current_state.status === 'first-selected-by-endcal') return notifyOther()
  	}
  
  	// helpers
  
  	function clearSelf () {
  		for (var i = 0; i < buttons.length; i++) {
  			buttons[i].classList.remove(css['date-in-range'])
  			buttons[i].classList.remove(css['date-selected'])
  		}		
  	}
  
  	function clearOther () {
  		current_state.second = void 0
  		$parent.notify($parent.make({ to: $parent.address, type: 'clear-other', data: { body: '' } }))
  	}
  
  	function clear_all () {
  		clearSelf()
  		clearOther()
  		current_state.first = current_state.second = void 0
  	}
  
  	function selectFirst (btn, current) {
  		clear_all()
  		btn.classList.add(css['date-selected'])
  		setStatus('first-selected-by-self')
  		current_state.first = current
  		$parent.notify($parent.make({ to: $parent.address, type: 'value-first', data: { body: [year, month+1, current_state.first] } }))
  	}
  
  	function selectSecond (btn, current) {
  		btn.classList.add(css['date-selected'])
  		setStatus('second-selected-by-self')
  		current_state.second = current
  		$parent.notify($parent.make({ to: $parent.address, type: 'value-second', data: { body: [year, month+1, current_state.second] } }))
  	}
  
  	function setStatus( nextStatus ) {
  		console.log('setStatus', JSON.stringify({ type: 'status', name,  data: { body: nextStatus } }, 0, 2))
  		current_state.status = nextStatus
  		$parent.notify($parent.make({ to: $parent.address, type: 'status', data: { status: nextStatus } }))
  	}
  
  	function render_new_cal(data) {
  		const { current } = data
  		let date = setMonth(new Date(), current)
  		let year = getYear(date)
  		let days = getDaysInMonth(date)
  		year = year
  		days = days
  
  		const cal = makeDays(days)
  		buttons = [...cal.children]
  		cal.onmousemove = onmousemove
  		cal.onclick = onclick
  		cal.onmouseleave = onmouseleave
  		cal.onmouseenter = onmouseenter
  		el.innerHTML = ''
  		el.append(cal)	
  	}
  
  	function markRange (A,B) {
  		console.log('mark range', {A, B})
  		if (A === B) return // onlyKeepFirst()
  		if (A < B) colorRange(A, B)
  		else colorRange(B, A)
  	}
  
  	function colorRange (start, end) {
  		buttons.map( btn => {
  			let current = parseInt(btn.dataset.num)
  			if (!current || btn.classList.contains(css["disabled-day"])) return
  			btn.classList.remove(css['date-in-range'])
  			if (current < start || current > end) {
  				btn.classList.remove(css['date-selected'])
  			}
  			if (current > start && current < end) {
  				console.log('adding date-in-range class for', {current})
  				btn.classList.add(css['date-in-range'])
  			}
  		})
  	}
  		
  	function notifyOther () { $parent.notify($parent.make({ to: $parent.address, type: 'selecting-second' })) }
  
  	function makeDays (days) {
  		const el = bel`<section role="calendar-days" class=${css["calendar-days"]}></section>`
  		// make space for week
  		getSpaceInPrevMonth(el)
  
  		for (let i = 1; i < days + 1; i++) {
  			let formatDate = format(new Date(year, month, i), 'd MMMM yyyy, EEEE')
  			let btn = bel`<button role="button" aria-selected="false" tabindex="-1" data-num="${i}" aria-label="${formatDate}" data-date="${year}-${month+1}-${i}">${i}</button>`
  			if (isToday(new Date(year, month, i)) ) {
  				btn.classList.add(css.today)
  				btn.setAttribute('aria-today', true)
  			} else { 
  				btn.classList.add(css.day)
  				if ( isPast(new Date(year, month, i)) ) btn.classList.add(css["disabled-day"])
  				btn.setAttribute('aria-today', false)
  			}
  			el.append(btn)
  		}
  		
  		return el
  	}
  
  	function getSpaceInPrevMonth (el) {
  		// get days in previous month
  		let daysInPrevMonth = getDaysInMonth(new Date(year, month-1))
  		// get day in prev month which means to add how many spans
  		let dayInPrevMonth = getDay(new Date(year, month-1, daysInPrevMonth))
  		for (let s = dayInPrevMonth; s > 0; s--) {
  				let span = bel`<div class=${css['day-prev']} role="presentation" aria-label aria-disabled="false"></div>`
  				el.append((span))
  		}
  	}
  
  }
  
  const css = csjs`
  .calendar-days {
      display: grid;
      grid-template-rows: auto;
      grid-template-columns: repeat(7, minmax(30px, auto));
      justify-items: center;
  }
  button {
      background: none;
      border: none;
      cursor: pointer;
  }
  .day {
      display: grid;
      align-items: center;
      justify-content: center;
      width: 30px;
      height: 30px;
      cursor: pointer;
      transition: color 0.25s, background-color 0.25s ease-in-out;
  }
  .day:hover {
      color: #fff;
      background-color: #000;
  }
  .today {
      background-color: #f2f2f2;
  }
  .date-selected, .date-selected:hover {
      color: #fff;
      background-color: #000;
  }
  .day-prev {}
  .disabled-day, .disabled-day:hover {
      color: #BBBBBB;
      background: none;
      cursor: default;
  }
  .date-in-range {
      color: #000;
      background-color: #EAEAEA;
  }
  `