package xyz.danielcortes.controllers.libro;

import java.util.List;
import java.util.Objects;
import javax.swing.JOptionPane;
import xyz.danielcortes.framework.GeneralValidator;
import xyz.danielcortes.models.Autor;
import xyz.danielcortes.models.Categoria;
import xyz.danielcortes.models.Editorial;
import xyz.danielcortes.models.Idioma;
import xyz.danielcortes.models.Libro;
import xyz.danielcortes.repository.LibroRepository;

public class LibroValidator {

  private LibroRepository libroRepository;

  LibroValidator(LibroRepository libroRepository) {
    this.libroRepository = libroRepository;
  }

  boolean validateLibro(Libro libro) {
    if (libro == null) {
      JOptionPane.showMessageDialog(
          null,
          "No hay Libro seleccionado",
          "Error",
          JOptionPane.ERROR_MESSAGE
      );
      return false;
    }
    return true;
  }

  boolean validateSerie(String serie) {
    if (serie == null) {
      JOptionPane.showMessageDialog(
          null,
          "La serie es nula",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (serie.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "La serie esta vacia",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (!GeneralValidator.isLong(serie)) {
      JOptionPane.showMessageDialog(
          null,
          "La serie no es numero valido",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateSerie(String serie, Libro original) {
    if (!validateSerie(serie))
      return false;

    Integer s = Integer.parseInt(serie);
    if (libroRepository.exists(s, original.getId())) {
      JOptionPane.showMessageDialog(
          null,
          "El numero de serie ya existe",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateISBN(String isbn) {
    if (isbn == null) {
      JOptionPane.showMessageDialog(
          null,
          "El ISBN es nulo",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (isbn.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "El ISBN esta vacio",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    isbn = isbn.replaceAll("[^\\d]", "");
    if ((isbn.length() == 13 && !ISBN13CheckSum(isbn))
        || (isbn.length() == 10 && !ISBN10CheckSum(isbn))
        || (isbn.length() != 10 && isbn.length() != 13)) {
      JOptionPane.showMessageDialog(
          null,
          "El ISBN no es valido",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return true;
  }

  boolean validateTitulo(String titulo) {
    if (titulo == null) {
      JOptionPane.showMessageDialog(
          null,
          "El titulo es nulo",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (titulo.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "El titulo esta vacio",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return true;
  }

  boolean validateNumeroPaginas(String numeroPaginas) {
    if (numeroPaginas == null) {
      JOptionPane.showMessageDialog(
          null,
          "El numero de paginas es nulo",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (numeroPaginas.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "El numero de paginas esta vacio",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (!GeneralValidator.isInteger(numeroPaginas)) {
      JOptionPane.showMessageDialog(
          null,
          "El numero de paginas no es un numero",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validatePrecioReferencia(String precioReferencia) {
    if (precioReferencia == null) {
      JOptionPane.showMessageDialog(
          null,
          "El precio referencial es nulo",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (precioReferencia.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "El precio referencial esta vacio",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (!GeneralValidator.isInteger(precioReferencia)) {
      JOptionPane.showMessageDialog(
          null,
          "El precio referencial no es un numero",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateAnoPublicacion(String anoPublicacion) {
    if (anoPublicacion == null) {
      JOptionPane.showMessageDialog(
          null,
          "El año de publicacion es nulo",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (anoPublicacion.isEmpty()) {
      JOptionPane.showMessageDialog(
          null,
          "El año de publicacion esta vacio",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (!GeneralValidator.isInteger(anoPublicacion)) {
      JOptionPane.showMessageDialog(
          null,
          "El año de publicacion no es un numero",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (!GeneralValidator.isYear(anoPublicacion)) {
      JOptionPane.showMessageDialog(
          null,
          "El año de publicacion no es un año valido",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return true;
  }

  boolean validateIdiomas(List<Idioma> idiomas) {
    if (idiomas.size() == 0) {
      JOptionPane.showMessageDialog(
          null,
          "No hay idiomas seleccionados",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (idiomas.stream().anyMatch(Objects::isNull)) {
      JOptionPane.showMessageDialog(
          null,
          "Se selecciono un idioma no existente",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateAutores(List<Autor> autores) {
    if (autores.size() == 0) {
      JOptionPane.showMessageDialog(
          null,
          "No hay autores seleccionados",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (autores.stream().anyMatch(Objects::isNull)) {
      JOptionPane.showMessageDialog(
          null,
          "Se selecciono un autor no existente",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateCategorias(List<Categoria> categorias) {
    if (categorias.size() == 0) {
      JOptionPane.showMessageDialog(
          null,
          "No hay autores seleccionados",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    if (categorias.stream().anyMatch(Objects::isNull)) {
      JOptionPane.showMessageDialog(
          null,
          "Se selecciono una categoria no existente",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  boolean validateEditorial(Editorial editorial) {
    if (editorial == null) {
      JOptionPane.showMessageDialog(
          null,
          "No hay editorial seleccionada",
          "Error",
          JOptionPane.ERROR_MESSAGE);
      return false;
    }

    return true;
  }

  private boolean ISBN10CheckSum(String isbn) {
    if (isbn.length() != 10)
      return false;

    int sum = 0;
    for (int i = 0; i < 9; i++) {
      int digit = isbn.charAt(i) - '0';
      if (0 > digit || 9 < digit)
        return false;
      sum += (digit * (10 - i));
    }

    char last = isbn.charAt(9);
    if ((last != 'X') && ((last < '0') || (last > '9')))
      return false;

    if (last == 'X')
      sum += 10;
    else
      sum += last - '0';

    return (sum % 11 == 0);
  }

  private boolean ISBN13CheckSum(String isbn) {
    if (isbn.length() != 13)
      return false;

    int sum = 0;
    for (int i = 0; i < 12; i++) {
      int digit = isbn.charAt(i) - '0';
      if (0 > digit || 9 < digit)
        return false;
      if (i % 2 == 0) {
        sum += digit;
      } else {
        sum += digit * 3;
      }
    }

    char last = isbn.charAt(12);
    if (((last < '0') || (last > '9')))
      return false;

    return (10 - (sum % 10) == last - '0');
  }

}
