const filterStyle = document.createElement('style')
document.head.appendChild(filterStyle)
const selected = new Set()
for (const checkbox of document.getElementsByClassName('filter-checkbox')) {
  const className = `project-${checkbox.id.replace('filter-by-', '')}`
  checkbox.addEventListener('change', e => {
    if (checkbox.checked) {
      selected.add(className)
      unselect()
      lastSelected = null
    } else {
      selected.delete(className)
    }
    if (selected.size === 0) {
      filterStyle.textContent = ''
    } else {
      filterStyle.textContent = `.project{display:none}${Array.from(
        selected,
        className => '.' + className
      ).join('')}{display:block}`
    }
  })
}

for (const label of document.getElementsByClassName('filter-tag')) {
  // Prevent selecting text when spam clicking button
  // Why not CSS? This way, you can still select the text by other means, like
  // with normal <button>s
  label.addEventListener('mousedown', e => {
    e.preventDefault()
  })
}

function empty (elem) {
  while (elem.firstChild) elem.removeChild(elem.firstChild)
}

const descElems = {
  wrapper: document.getElementById('description-wrapper'),
  title: document.getElementById('desc-title'),
  link: document.getElementById('desc-link'),
  tags: document.getElementById('desc-tags'),
  text: document.getElementById('description')
}
function createTag (tagElem) {
  const tag = document.createElement('div')
  tag.className = 'desc-tag'
  const icon = document.createElement('div')
  icon.className = `desc-tag-icon base-tag ${[...tagElem.classList].find(cls =>
    cls.startsWith('tag-')
  )}`
  const name = document.createElement('div')
  name.className = 'desc-tag-name'
  name.textContent = tagElem.title
  tag.append(icon, name)
  return tag
}
function setDescription (project) {
  descElems.title.textContent = project.querySelector('.title').textContent
  descElems.link.href = project.href
  empty(descElems.tags)
  for (const tag of project.getElementsByClassName('tag')) {
    descElems.tags.append(createTag(tag))
  }
  empty(descElems.text)
  for (const paragraph of project.dataset.desc.split(/\r?\n/)) {
    const p = document.createElement('p')
    p.textContent = paragraph
    descElems.text.append(p)
  }
}
function unselect () {
  descElems.wrapper.style.display = 'none'
  if (lastSelected) {
    lastSelected.classList.remove('showing-desc')
    lastSelected.ariaExpanded = 'false'
  }
}

const projectsWrapper = document.getElementById('projects-wrapper')
let lastSelected = null
projectsWrapper.addEventListener('click', e => {
  const project = e.target.closest('.project')
  if (!project) {
    return
  }
  const showInfoHidden =
    window.getComputedStyle(project.querySelector('.show-info')).display ===
    'none'
  if (showInfoHidden || e.target.closest('.show-info')) {
    e.preventDefault()
    unselect()
    if (lastSelected !== project) {
      setDescription(project)
      project.after(descElems.wrapper)
      descElems.wrapper.style.display = null
      lastSelected = project
      project.classList.add('showing-desc')
      project.ariaExpanded = 'true'
    } else {
      lastSelected = null
    }
  }
})

for (const project of document.getElementsByClassName('project')) {
  project.ariaExpanded = 'false'
}

function easeInOutCubic (t) {
  t *= 2
  if (t < 1) return (t * t * t) / 2
  t -= 2
  return (t * t * t + 2) / 2
}

const BIRTHDAY = 1049933280000 // new Date('2003-04-09T17:08-07:00').getTime()
const MS_IN_YR = 1000 * 60 * 60 * 24 * 365.242199
function getAge (now = Date.now()) {
  // Could be 15, but it gets imprecise at such a small scale, and the animation
  // looks unlike the others
  return ((now - BIRTHDAY) / MS_IN_YR).toFixed(13)
}
const ANIM_LENGTH = 500 // ms
const ALPHA = 0.8

const ageSpan = document.getElementById('age')
ageSpan.textContent = Math.floor((Date.now() - BIRTHDAY) / MS_IN_YR)
ageSpan.classList.add('age-clickable')
ageSpan.tabIndex = 0
ageSpan.title = 'Click to see me age in real time'
ageSpan.addEventListener(
  'click',
  e => {
    const ageWrapper = document.createElement('code')
    ageWrapper.classList.add('age')
    ageWrapper.role = 'text'
    const age = getAge()
    ageWrapper.style.width = age.length + 'ch'
    const decimal = age.indexOf('.')
    const digits = new Array(age.length)
    let sigfigs = Math.floor((Date.now() - BIRTHDAY) / 10000).toString().length
    for (let i = 0; i < age.length; i++) {
      const digit = document.createElement('span')
      digits[i] = {
        elem: digit,
        exponent:
          i === decimal ? null : i < decimal ? decimal - i - 1 : decimal - i
      }
      if (age[i] !== '.') {
        if (sigfigs <= 0) {
          digit.classList.add('insignificant')
          digit.title = 'This digit is purely an estimation.'
        }
        sigfigs--
      } else {
        digit.textContent = '.'
        digit.style.transform = `translate3d(${i}ch, 0, 0)`
      }
      ageWrapper.append(digit)
    }
    ageWrapper.append('\xa0') // nbsp
    ageSpan.replaceWith(ageWrapper)
    function display () {
      const now = Date.now()
      const age = getAge(now)
      for (let i = 0; i < age.length; i++) {
        const digit = digits[i]
        if (digit.exponent !== null) {
          const interval = 10 ** digit.exponent * MS_IN_YR
          const animationTime = Math.min(interval, ANIM_LENGTH)
          const time = (now - BIRTHDAY) % interval
          if (digit.elem.textContent !== age[i]) {
            digit.elem.textContent = age[i]
          }
          if (time < animationTime) {
            const interp = easeInOutCubic(time / animationTime)
            digit.elem.style.transform = `translate3d(${i}ch, ${
              interp - 1
            }em, 0)`
            digit.elem.style.color = `rgba(255, 255, 255, ${interp * ALPHA})`
            digit.elem.style.setProperty(
              '--last',
              `rgba(255, 255, 255, ${(1 - interp) * ALPHA})`
            )
            digit.elem.dataset.last = (+age[i] + 9) % 10
            digit.wasStatic = false
          } else if (!digit.wasStatic) {
            digit.elem.style.transform = `translate3d(${i}ch, 0, 0)`
            digit.elem.style.color = null
            digit.elem.style.removeProperty('--last')
            delete digit.elem.dataset.last
            digit.wasStatic = true
          }
        }
      }
      window.requestAnimationFrame(display)
    }
    display()
  },
  { once: true }
)
