let // Global variables
  headSection = document.querySelector('.head')
  , password = document.querySelector('.password')
  , button = document.querySelector('.copy.button')
  , symbolsButton = document.querySelector('.settings .symbols')
  , symbolsCheckBox = document.querySelector('.symbols .material-icons')
  , slider = document.querySelector('#slider')
  , sliderValue = document.querySelector('.output .value')
  // The initial state of the settings
  , selectionState = {
      'symbols': false
    };

/*
 * The alphanumeric characters and symbols
 * used to generate passwords
 */
const CHARSET = {
  'numeric' : '0123456789',
  'alpha': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  'symbols': '/^_@&[<->]\:{.+},$'
};


/*
 * Load the functions to generate the password
 */
window.onload = (e) => {
  password.value = renderPassword(slider.value, selectionState['symbols']);
  // Regenerate password on these events
  changePasswordOnSlide(e);
  reloadPassword(e);
  symbolButtonHandler(e);
};


/*
 * Toggle the symbol button between true/false state
 */
const symbolButtonHandler = (e) => {
  symbolsButton.addEventListener('click', (e) => { 
    let renderSymbol = selectionState['symbols'] = !selectionState['symbols'];
    password.value = renderPassword(slider.value, renderSymbol);
    
    // Disable/enable symbols in password
    symbolsCheckBox.textContent
      = selectionState['symbols']
      ? 'radio_button_checked'
      : 'radio_button_unchecked';
  });
}


/*
 * Handle the copy-to-clipboard functionality
 */
const copyToClipboard = () => {
  // Select & copy the password value
  button.innerText = 'assignment_turned_in';
  password.select();
  document.execCommand('copy');
  // Return to original state
  setTimeout(() => {
    button.innerText = 'sync';
    headSection.classList.remove('selected');
  }, 400);
}


/*
 * The logic to generate a random string
 *
 * @param charset    String characters use for the password
 * @param len        The desired length of the password via the slider
 */
const generatePassword = (charset, len) => {
  var result = "";
  for (var i = 0; i < len; i++) {
    result += charset[Math.floor(Math.random() * 52 + 1)];
  }
  // Ensure we only return the exact length
  return result.substr(0, len);
}


/*
 * The logic to regenerate password when using the slider
 */
const changePasswordOnSlide = (e) => {
  slider.oninput = (e) => {
    sliderValue.textContent = slider.value;
    setTimeout(() => {
      // Generate password on slide
      password.value = renderPassword(slider.value);
      headSection.classList.add('selected');
      copyToClipboard();
      // Return to original state
      setTimeout(() => {
        headSection.classList.remove('selected');
      }, 400);
    }, 0)
  };
}


/*
 * The logic to regenerate password when
 * the reload button is clicked
 */
const reloadPassword = (e) => {
  button.addEventListener('click', (e) => { 
    setTimeout(() => {
      copyToClipboard();
    }, 0
     , password.value = renderPassword(slider.value)
     , headSection.classList.add('selected')
    )
  })
}


/*
 * Determine if the symbol is enabled and merge all of the combined 
 * alphanumeric characters and symbol from the charset
 *
 * @param len              The desired length of the password via the slider
 * @param renderSymbols    Determined if symbol are included in the password
 */
const renderPassword = (len, renderSymbols = selectionState['symbols']) => {
  let charSet = CHARSET['numeric'].split('').concat(
        renderSymbols ? CHARSET['symbols'].split('') : [],
        CHARSET['alpha'].split('')
      );
  return generatePassword(charSet, len)
}