/* global chrome */
const COCHAV_HANOFESH_URL = 'https://cochav-hanofesh.com/?source=chrome_ext';

/** Email autocomplete; **/
let suffixList = [];
chrome.storage.sync.get('options', (storage) => {
  suffixList = (storage.options && storage.options.autocompleteEmailList
    ? storage.options.autocompleteEmailList
    : []);
});

const emailAutocompleteExt = document.createElement('div');
emailAutocompleteExt.className = 'email-autocomplete-ext';
document.body.appendChild(emailAutocompleteExt);

const autocompleteElement = document.querySelector('.email-autocomplete-ext');
let isShown = false;

function showAutocompleteElement (value, position, targetField) {
  if (isShown) {
    return;
  }

  const suffixesHtml = suffixList.map(suffix => `<div class="email-complete-value" tabindex="1" data-suffix="${suffix}"><span>${value}</span><span class="suffix">@${suffix}</span></div>`).join('');
  const creditHtml = '<div class="email-complete-credit"><a>כוכב הנופש</a></div>';
  autocompleteElement.innerHTML = suffixesHtml + creditHtml;
  autocompleteElement.style.display = 'block';
  autocompleteElement.style.top = position.top || 'auto';
  autocompleteElement.style.right = position.right || 'auto';
  autocompleteElement.style.left = position.left || 'auto';
  isShown = true;

  setupAutocompleteListeners(targetField);
}

function setupAutocompleteListeners (targetField) {
  autocompleteElement.querySelectorAll('.email-complete-value').forEach((value) => {
    value.completeEmailHandler = () => {
      completeEmail(targetField, value.getAttribute('data-suffix'));
    };
    value.keydownHandler = (event) => {
      if (event.keyCode === 13) {
        event.preventDefault();
        event.stopPropagation();
        completeEmail(targetField, value.getAttribute('data-suffix'));
      }
    };
    value.addEventListener('mousedown', value.completeEmailHandler);
    value.addEventListener('keydown', value.keydownHandler);
    value.setAttribute('tabindex', '0');
  });

  const creditElement = autocompleteElement.querySelector('.email-complete-credit');
  creditElement.clickHandler = () => {
    const win = window.open(COCHAV_HANOFESH_URL, '_blank');
    win.focus();
  };
  creditElement.addEventListener('click', creditElement.clickHandler);

  document.addEventListener('click', hideAutocompleteElement);
  document.addEventListener('keydown', navigationListener);
}

function navigationListener (event) {
  let action;
  const focusedElement = autocompleteElement.querySelector('.focus');
  const allElements = Array.from(autocompleteElement.querySelectorAll('.email-complete-value'));
  if (event.keyCode === 13 && focusedElement) {
    event.preventDefault();
    event.stopPropagation();
    const suffix = focusedElement.getAttribute('data-suffix');
    const targetField = document.activeElement;
    if (suffix && targetField) {
      completeEmail(targetField, suffix);
    }
    return;
  } else if (event.keyCode === 40) { // Down arrow
    event.preventDefault();
    event.stopPropagation();
    action = 1;
  } else if (event.keyCode === 38) { // Up arrow
    event.preventDefault();
    event.stopPropagation();
    action = -1;
  }

  if (!action) {
    return;
  }

  let currentIndex = focusedElement ? allElements.indexOf(focusedElement) : -1;
  allElements.forEach(el => el.classList.remove('focus'));
  if (currentIndex === -1) {
    currentIndex = action > 0 ? -1 : allElements.length;
  }
  currentIndex += action;
  if (currentIndex >= allElements.length) {
    currentIndex = 0;
  }
  if (currentIndex < 0) {
    currentIndex = allElements.length - 1;
  }
  allElements[currentIndex].classList.add('focus');
  allElements[currentIndex].focus();
}

function hideAutocompleteElement () {
  const elements = autocompleteElement.querySelectorAll('.email-complete-value');
  elements.forEach(el => {
    el.removeEventListener('mousedown', el.completeEmailHandler);
    el.removeEventListener('keydown', el.keydownHandler);
  });
  const creditElement = autocompleteElement.querySelector('.email-complete-credit');
  if (creditElement && creditElement.clickHandler) {
    creditElement.removeEventListener('click', creditElement.clickHandler);
  }
  autocompleteElement.style.display = 'none';
  autocompleteElement.innerHTML = '';
  document.removeEventListener('click', hideAutocompleteElement);
  document.removeEventListener('keydown', navigationListener);
  isShown = false;
}

function lastCharIsAt (event, targetField, targetFieldValue) {
  const tag = targetField.tagName.toLowerCase();

  if ((tag !== 'input' && tag !== 'textarea') ||
    targetField.type === 'password' ||
    window.getComputedStyle(targetField).webkitTextSecurity === 'disc' ||
    (event.data !== '@' && targetFieldValue[targetFieldValue.length - 1] !== '@') ||
    (targetField.selectionEnd && targetField.selectionEnd < targetFieldValue.length)) {
    return false;
  }

  const emailValue = targetFieldValue.split(' ')[targetFieldValue.split(' ').length - 1].slice(0, -1) || '';

  if (!emailValue.trim().length ||
    emailValue.includes('@')) {
    return false;
  }

  return true;
}

function completeEmail (inputElement, value) {
  inputElement.focus();
  const valueToPaste = inputElement.value + value;
  inputElement.value = valueToPaste;
  inputElement.dispatchEvent(new Event('input', {
    bubbles: true,
    cancelable: true
  }));

  setTimeout(() => {
    inputElement.focus();
  });
  hideAutocompleteElement();
}

document.addEventListener('input', (event) => {
  if (!suffixList.length) {
    return;
  }

  const targetField = event.target;
  const targetFieldValue = targetField.value;

  if (lastCharIsAt(event, targetField, targetFieldValue)) {
    const emailValue = targetFieldValue.split(' ')[targetFieldValue.split(' ').length - 1].slice(0, -1) || '';

    const topPosition = targetField.getBoundingClientRect().top + targetField.offsetHeight + 5;
    let leftPosition;
    let rightPosition;

    const computedStyle = window.getComputedStyle(targetField);
    if (computedStyle.textAlign === 'left' ||
      (computedStyle.direction === 'ltr' && computedStyle.textAlign === 'start')) {
      leftPosition = targetField.getBoundingClientRect().left + 1;
    } else {
      rightPosition = document.documentElement.offsetWidth - targetField.getBoundingClientRect().right + 1;
    }

    showAutocompleteElement(emailValue, {
      top: topPosition + 'px',
      left: leftPosition ? leftPosition + 'px' : 'auto',
      right: rightPosition ? rightPosition + 'px' : 'auto'
    }, targetField);
  } else if (isShown) {
    hideAutocompleteElement();
  }
});

/** Paste Email **/
function insertTextAtCursor (text) { // source: stackoverflow.com/questions/2920150/
  let sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();
      range.insertNode(document.createTextNode(text));
      sel.collapseToEnd();
    }
  }
}

function insertTextAtCursorInInputs (element, text) {
  const posStart = element.selectionStart;
  const posEnd = element.selectionEnd;
  const currentValueStart = element.value.slice(0, posStart);
  const currentValueEnd = element.value.slice(posEnd);

  element.value = currentValueStart + text + currentValueEnd;
  element.dispatchEvent(new Event('input', {
    bubbles: true,
    cancelable: true
  }));

  const moveCursorTo = currentValueStart.length + text.length;
  element.setSelectionRange(moveCursorTo, moveCursorTo);
}

function insertWord (element, value) {
  if (!element || !value) {
    return;
  }

  const tag = element.tagName.toLowerCase();
  if (tag === 'input' || tag === 'textarea') {
    insertTextAtCursorInInputs(element, value);
  } else {
    insertTextAtCursor(value);
  }
}

let focusedElement;
window.addEventListener('contextmenu', (event) => {
  focusedElement = event.target;
}, false);

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'paste') {
    insertWord(focusedElement, request.value);
  }
  return true;
});
