document.addEventListener('DOMContentLoaded', function () {

  const elementGlyphSearch = document.getElementById('glyphSearch');
  const elementGlyphSearchButton = document.getElementById('glyphSearchButton');
  const elementGlyphSearchAllButton = document.getElementById('glyphSearchAllButton');
  const elementGlyphCheatSheet = document.getElementById('glyphCheatSheet');

  // nice scrolling

  document.getElementsByTagName('nav')[0].addEventListener('click', function (e) {
    if (e.target.matches('a') && e.target.hash) {
      const section = document.getElementById(e.target.hash.slice(1));

      if (section) {
        e.preventDefault();
        scrollIt(section);
      }
    }
  });

  function scrollIt(destination, duration = 200, easing = 'linear', callback) {

    const easings = {
      linear(t) {
        return t;
      },
      easeInQuad(t) {
        return t * t;
      },
      easeOutQuad(t) {
        return t * (2 - t);
      },
      easeInOutQuad(t) {
        return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
      },
      easeInCubic(t) {
        return t * t * t;
      },
      easeOutCubic(t) {
        return (--t) * t * t + 1;
      },
      easeInOutCubic(t) {
        return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
      },
      easeInQuart(t) {
        return t * t * t * t;
      },
      easeOutQuart(t) {
        return 1 - (--t) * t * t * t;
      },
      easeInOutQuart(t) {
        return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
      },
      easeInQuint(t) {
        return t * t * t * t * t;
      },
      easeOutQuint(t) {
        return 1 + (--t) * t * t * t * t;
      },
      easeInOutQuint(t) {
        return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t;
      }
    };

    const start = window.pageYOffset;
    const startTime = 'now' in window.performance ? performance.now() : new Date().getTime();

    const documentHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
    const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
    const destinationOffset = typeof destination === 'number' ? destination : destination.offsetTop;
    const destinationOffsetToScroll = Math.round(documentHeight - destinationOffset < windowHeight ? documentHeight - windowHeight : destinationOffset);

    if ('requestAnimationFrame' in window === false) {
      window.scroll(0, destinationOffsetToScroll);
      if (callback) {
        callback();
      }
      return;
    }

    function scroll() {
      const now = 'now' in window.performance ? performance.now() : new Date().getTime();
      const time = Math.min(1, ((now - startTime) / duration));
      const timeFunction = easings[easing](time);
      window.scroll(0, Math.ceil((timeFunction * (destinationOffsetToScroll - start)) + start));

      if (window.pageYOffset === destinationOffsetToScroll) {
        if (callback) {
          callback();
        }
        return;
      }

      requestAnimationFrame(scroll);
    }

    scroll();
  }

  // search via typing in input (debounced)
  elementGlyphSearch && elementGlyphSearch.addEventListener(
    'keyup',
    debounce(function (e) {
      gtag('event', 'search-via-input', {
        event_category: 'glyph-search',
        event_label: 'Cheat Sheet : ' + (e.target && e.target.value),
        value: e.target && e.target.value
      });
      searchGlyphs();
    }, 500)
  );

  // search via search button
  elementGlyphSearchButton && elementGlyphSearchButton.addEventListener(
    'click',
    () => {
      gtag('event', 'search-via-button', {
        event_category: 'glyph-search',
        event_label: 'Cheat Sheet : ' + (e.target && e.target.value),
        value: e.target && e.target.value
      });
      searchGlyphs();
    }
  )

  // search all via search all button
  elementGlyphSearchAllButton && elementGlyphSearchAllButton.addEventListener(
    'click',
    () => {
      gtag('event', 'search-all-via-button', {
        event_category: 'glyph-search',
        event_label: 'Cheat Sheet : all',
        value: 'all'
      });
      searchAllGlyphs();
    }
  );

  // Credit David Walsh (https://davidwalsh.name/javascript-debounce-function)
  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  function debounce(func, wait, immediate) {
    var timeout;

    return function executedFunction() {
      var context = this;
      var args = arguments;

      var later = function () {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };

      var callNow = immediate && !timeout;

      clearTimeout(timeout);

      timeout = setTimeout(later, wait);

      if (callNow) func.apply(context, args);
    };
  }

  function searchAllGlyphs() {
    elementGlyphSearch.value = '';
    searchGlyphs();
  }

  function searchGlyphs() {
    const filter = elementGlyphSearch.value.toLowerCase();
    const elements = elementGlyphCheatSheet.querySelectorAll('.column');
    const length = elements.length;
    let i = 0;
    let elementClassName, elementCodePoint;
    let anyVisibleColumns = false;

    for (; i < length; i++) {
      elementClassName = elements[i].querySelector('div.class-name');
      elementCodePoint = elements[i].querySelector('div.codepoint');
      if (elementClassName && elementCodePoint) {
        if (
          elementClassName
            .textContent
            .indexOf(filter) > -1 ||
          elementCodePoint
            .textContent
            .indexOf(filter) > -1
        ) {
          elementClassName.parentNode.classList.add('is-visible');
          anyVisibleColumns = true;
        } else {
          elementClassName.parentNode.classList.remove('is-visible');
        }
      }
    }

    if (anyVisibleColumns) {
      elementGlyphCheatSheet.classList.add('has-results');
    }
    else {
      elementGlyphCheatSheet.classList.remove('has-results');
    }
  }

  // extremely basic filtering on load:
  function getParameterByName(name, url) {
    if (!url) {
      url = window.location.href;
    }
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
      results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
  }

  const set = getParameterByName('set');
  const onCheatSheet = window.location.href.indexOf('/cheat-sheet') !== -1;

  if (set) {
    if (onCheatSheet) {
      elementGlyphSearch.value = set;
      gtag('event', 'search-via-url', {
        event_category: 'glyph-search',
        event_label: 'Cheat Sheet : ' + set,
        value: set
      });
      searchGlyphs();
    } else {
      gtag('event', 'search-via-redirect', {
        event_category: 'glyph-search',
        event_label: 'Cheat Sheet : ' + set,
        value: set
      });
      // redirect to cheat sheet with param
      window.location.href = window.location.origin + '/cheat-sheet?set=' + set;
    }
  }

  /* hold on to yer' butts */

  // Copies a string to the clipboard. Must be called from within an
  // event handler such as click. May return false if it failed, but
  // this is not always possible. Browser support for Chrome 43+,
  // Firefox 42+, Safari 10+, Edge and IE 10+.
  // IE: The clipboard feature may be disabled by an administrator. By
  // default a prompt is shown the first time the clipboard is
  // used (per session).
  function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
      // IE specific code path to prevent textarea being shown while dialog is visible.
      return clipboardData.setData('Text', text);
    } else if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
      var textarea = document.createElement('textarea');
      textarea.textContent = text;
      textarea.style.position = 'fixed'; // Prevent scrolling to bottom of page in MS Edge.
      document.body.appendChild(textarea);
      textarea.select();
      try {
        return document.execCommand('copy'); // Security exception may be thrown by some browsers.
      } catch (ex) {
        console.warn('Copy to clipboard failed.', ex);
        return false;
      } finally {
        document.body.removeChild(textarea);
      }
    }
  }

  elementGlyphCheatSheet && elementGlyphCheatSheet.addEventListener(
    'mouseenter',
    function (e) {
      if (e.target.classList.contains('column')) {
        // add Node
        const newNode = document.createElement('span');
        const copyTextNode = document.createElement('span');
        const copyGlyphNode = document.createElement('span');
        const copyClassNode = document.createElement('span');
        const copyCodePoint = document.createElement('span');
        newNode.className = 'glyph-popout-copy-clipboard';
        copyTextNode.innerText = 'Copy';
        copyGlyphNode.innerText = 'Icon';
        copyClassNode.innerText = 'Class';
        copyCodePoint.innerText = 'UTF';
        copyGlyphNode.title = 'Copy Icon to Clipboard';
        copyClassNode.title = 'Copy Class Name to Clipboard';
        copyCodePoint.title = 'Copy UTF-16 Codes to Clipboard';
        copyGlyphNode.className = 'copy-glyph';
        copyClassNode.className = 'copy-class';
        copyCodePoint.className = 'copy-utf16';
        newNode.appendChild(copyTextNode);
        newNode.appendChild(copyGlyphNode);
        newNode.appendChild(copyClassNode);
        newNode.appendChild(copyCodePoint);
        e.target.children[0].before(newNode);
      }
    },
    true
  );

  elementGlyphCheatSheet && elementGlyphCheatSheet.addEventListener(
    'mouseleave',
    function (e) {
      if (e.target.classList.contains('column')) {
        e.target.querySelector('.glyph-popout-copy-clipboard').remove();
      }
    },
    true
  );

  elementGlyphCheatSheet && elementGlyphCheatSheet.addEventListener('click', function (event) {
    let textToCopy = '';
    let target = event.target;
    let parent = target.parentNode;
    if (parent.className === 'glyph-popout-copy-clipboard') {
      if (target.className === 'copy-class') {
        textToCopy = parent.parentNode.querySelector('.class-name').innerText;
      } else if (target.className === 'copy-glyph') {
        textToCopy = window
          .getComputedStyle(document.querySelector(`.${parent.parentNode.querySelector('.class-name').innerText}`), ':before')
          .getPropertyValue('content')
          .replace(/"/g, '');
      } else if (target.className === 'copy-utf16') {
        const glyph = window
          .getComputedStyle(document.querySelector(`.${parent.parentNode.querySelector('.class-name').innerText}`), ':before')
          .getPropertyValue('content')
          .replace(/"/g, '');
        textToCopy = '';
        let i = 0;
        while (i < 10) {
          let c = glyph.charCodeAt(i); // js strings are utf16 already :-)
          if (!(c > 0)) break;
          if (c < 0x32) continue;
          if (i) textToCopy += ' ';
          textToCopy += glyph.charCodeAt(i++).toString(16);
        }
      }
    } else if (parent.className.startsWith('column') && target.className === 'codepoint') {
        textToCopy = parent.parentNode.querySelector('.codepoint').innerText;
    }
    if (textToCopy.length > 0) {
      gtag('event', event.target.className, {
        event_category: 'clipboard-copy',
        event_label: 'Copy To Clipboard : ' + textToCopy,
        value: textToCopy
      });
      copyToClipboard(textToCopy);
    }
  });

  // lazy load images
  (function lazyLoadImages() {
    const imageObserver = new IntersectionObserver((entries, imgObserver) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
        }
      });
    });
    const arr = document.querySelectorAll('img.lzy_img');
    arr.forEach(v => {
      imageObserver.observe(v);
    });
  })();

});