/*
 * Form validators. They'll find, render and focus error/s and
 * prevent form submission.
 */

/*
 * Calls specified validator along with the arguments on form submition.
 */
$.fn.onSubmitValidator = function(validatorCb) {
  var params = Array.prototype.slice.call(arguments, 1);
  var $form = $(this);
  if ($form.length) {
    $form.submit(function (ev) {
      $form.clearFormErrors();
      params.unshift(ev);
      validatorCb.apply(this, params);
    });
  }
};

/*
 * @param {boolean} clearErr Set clearErr to true if this is the only
 * error that can happen/show.
 */
function textValidator(ev, textInput, textLimitMin, textLimitMax, clearErr, tinyMCEInput) {
  clearErr = _.isUndefined(clearErr) ? false : clearErr;

  if(tinyMCEInput){
    var text = tinyMCEInput;
  } else {
    var text = $(textInput).val().trim();
    $(textInput).val(text);
    var text_from_html = $("<div/>").html(text).text();
    if (text_from_html.length < text.length) text = text_from_html;
  }

  var nameTooShort = text.length < textLimitMin;
  var nameTooLong = text.length > textLimitMax;

  var errMsg;
  if (nameTooShort) {
    if (textLimitMin === 1) {
      errMsg = I18n.t("general.text.not_blank");
    } else {
      errMsg = I18n.t("general.text.length_too_short", { min_length: textLimitMin });
    }
  } else if (nameTooLong) {
    if(tinyMCEInput){
      errMsg = I18n.t("general.text.length_too_long_general");
    } else {
      errMsg = I18n.t("general.text.length_too_long", { max_length: textLimitMax });
    }
  }

  var noErrors = _.isUndefined(errMsg);
  if (!noErrors) {
    renderFormError(ev, textInput, errMsg, clearErr);
  }
  return noErrors;
}

function checklistsValidator(ev, checklists, editMode) {
  var noErrors = true;
  // For every visible (i.e. not removed) checklist
  $(checklists).each(function() {
    var $checklist = $(this);
    if ($checklist.css('display') != 'none') {

      // For every visible (i.e. not removed) ckecklist item
      anyChecklistItemFilled = false;
      $(" .checklist-item-text", $checklist).each(function() {
        var $itemInput = $(this);
        var $item = $itemInput.closest("fieldset");
        if ($item.css('display') != 'none') {

          if ($itemInput.val()) {
            var itemNameValid = textValidator(ev, $itemInput, 1,
              <%= Constants::TEXT_MAX_LENGTH %>);
            if (!itemNameValid) {
              noErrors = false;
            }
            anyChecklistItemFilled = true;
          } else {
            // Remove empty checklist item input
            $item.remove();
          }
        }
      })

      var $checklistInput = $checklist.find(".checklist-name");
      // In edit mode, checklist's name can't be blank if any items present
      var allowBlankChklstName = !(anyChecklistItemFilled || editMode);
      var textLimitMin = allowBlankChklstName ? 0 : 1;
      var checklistNameValid = textValidator(ev, $checklistInput,
        textLimitMin, <%= Constants::TEXT_MAX_LENGTH %>);
      if (!checklistNameValid) {
        noErrors = false;
      } else if (allowBlankChklstName) {
        // Hide empty checklist (remove would break server-side logic)
        $checklist.hide();
      }
    }
  });

  return noErrors;
}

var FileTypeEnum = Object.freeze({
  FILE: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB * 1024 * 1024,
  AVATAR: <%= Constants::AVATAR_MAX_SIZE_MB.megabytes %>
});

function filesValidator(ev, fileInputs, fileTypeEnum, canBeEmpty) {
  canBeEmpty = (typeof canBeEmpty !== 'undefined') ? canBeEmpty : false;
  var filesValid = true;
  if (fileInputs.length) {
    var filesPresentValid = canBeEmpty || filesPresentValidator(ev, fileInputs);
    var filesSizeValid = false;
    if (filesPresentValid) {
      filesSizeValid = filesSizeValidator(ev, fileInputs, fileTypeEnum);
    }
    // File spoof check is done on server-side only
    filesValid = filesPresentValid && filesSizeValid;
  }
  return filesValid;
}

function filesPresentValidator(ev, fileInputs) {
  var filesPresentValid = true;
  _.each(fileInputs, function(fileInput) {
    if (!fileInput.files[0]) {
      assetError = I18n.t("general.file.blank");
      renderFormError(ev, fileInput, assetError, false, "data-error='file-missing'");
      filesPresentValid = false;
    }
  });
  return filesPresentValid;
}

function filesSizeValidator(ev, fileInputs, fileTypeEnum) {

  function getFileTooBigError(file) {
    if (!file) {
      return ;
    }
    if (file.size > fileTypeEnum) {
      switch (fileTypeEnum) {
        case FileTypeEnum.FILE:
         return I18n.t('general.file.size_exceeded', { file_size: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB }).strToErrorFormat();
        case FileTypeEnum.AVATAR:
          return "<%= I18n.t 'general.file.size_exceeded', file_size: Constants::AVATAR_MAX_SIZE_MB %>".strToErrorFormat();
      }
    }
  };

  function checkFilesTotalSize(fileInputs) {
    if (!fileInputs || fileInputs < 2) {
      return ;
    }

    var size = 0;
    _.each(fileInputs, function(fileInput) {
      var file = fileInput.files[0]
      size += file.size;
    })

    if (size > fileTypeEnum) {
      switch (fileTypeEnum) {
        case FileTypeEnum.FILE:
          return I18n.t('general.file.total_size', { size: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB }).strToErrorFormat();
        case FileTypeEnum.AVATAR:
          return "<%= I18n.t('users.registrations.edit.avatar_total_size', size: Constants::AVATAR_MAX_SIZE_MB) %>".strToErrorFormat();
      }
    }
  }

  // Check if any file exceeds allowed size limit
  var filesSizeValid = true;

  // Check total size of uploaded files
  var totalSizeOK = checkFilesTotalSize(fileInputs);

  _.each(fileInputs, function(fileInput) {
    var file = fileInput.files[0];
    var assetError = getFileTooBigError(file);
    var assetError = totalSizeOK;
    if (assetError) {
      renderFormError(ev, fileInput, assetError, false, "data-error='file-size'");
      filesSizeValid = false;
    }
  });
  if(filesSizeValid) {
    // Check if there is enough free space for the files
    filesSizeValid = enoughSpaceValidator(ev, fileInputs);
  }
  return filesSizeValid;
}

function numberMinMaxValidator(value, min, max) {
  if(parseInt(value) < min || isNaN(value))
    return min;
  else if(parseInt(value) > max)
    return max;
  else return value;
}

/*
 * Overriden in billing module for checking whether enough
 * team space is free.
 */
function enoughSpaceValidator(ev, fileInputs) {
  return true;
}
