package xyz.danielcortes.controllers.libro;

import java.time.Year;
import java.util.HashSet;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import xyz.danielcortes.framework.JListUtils;
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.AutorRepository;
import xyz.danielcortes.repository.CategoriaRepository;
import xyz.danielcortes.repository.EditorialRepository;
import xyz.danielcortes.repository.IdiomaRepository;
import xyz.danielcortes.repository.LibroRepository;
import xyz.danielcortes.views.libro.LibroUpdatePanel;

public class LibroUpdateController {

  private LibroUpdatePanel view;
  private LibroValidator validator;
  private LibroRepository libroRepository;

  private IdiomaRepository idiomaRepository;
  private CategoriaRepository categoriaRepository;
  private AutorRepository autorRepository;
  private EditorialRepository editorialRepository;

  public LibroUpdateController(LibroUpdatePanel view) {
    this.view = view;
    this.libroRepository = new LibroRepository();
    this.validator = new LibroValidator(this.libroRepository);

    this.idiomaRepository = new IdiomaRepository();
    this.categoriaRepository = new CategoriaRepository();
    this.autorRepository = new AutorRepository();
    this.editorialRepository = new EditorialRepository();
    this.setupListeners();
  }

  private void setupListeners() {
    this.view.getLibroCombo().addActionListener(e -> {
      Libro libro = (Libro) this.view.getLibroCombo().getSelectedItem();
      if (libro == null)
        return;
      this.view.getSerieField().setText(String.valueOf(libro.getSerie()));
      this.view.getIsbnField().setText(libro.getIsbn());
      this.view.getTituloField().setText(libro.getTitulo());
      this.view.getPaginasField().setText(String.valueOf(libro.getNumeroPaginas()));
      this.view.getAnoPublicacionField().setText(String.valueOf(libro.getAnoPublicacion()));
      this.view.getPrecioReferenciaField().setText(String.valueOf(libro.getPrecioReferencia()));
      JListUtils.setSelectedValues(
          this.view.getIdiomasList(),
          libro.getIdiomas()
      );
      JListUtils.setSelectedValues(
          this.view.getAutoresList(),
          libro.getAutores()
      );
      JListUtils.setSelectedValues(
          this.view.getCategoriasList(),
          libro.getCategorias()
      );
      this.view.getEditorialCombo().setSelectedItem(libro.getEditorial());
    });
    this.view.getActualizarButton().addActionListener(e -> update());
  }

  private void update() {
    // @formatter:off
    Libro original = (Libro) this.view.getLibroCombo().getSelectedItem();
    if(!validator.validateLibro(original)) return;

    String serie = this.view.getSerieField().getText();
    if(!validator.validateSerie(serie, original)) return;

    String isbn = this.view.getIsbnField().getText();
    if(!validator.validateISBN(isbn)) return;
    isbn = isbn.replaceAll("[^\\d]", "");

    String titulo = this.view.getTituloField().getText();
    if(!validator.validateTitulo(titulo)) return;

    String numeroPaginas = this.view.getPaginasField().getText();
    if(!validator.validateNumeroPaginas(numeroPaginas)) return;

    String anoPublicacion = this.view.getAnoPublicacionField().getText();
    if(!validator.validateAnoPublicacion(anoPublicacion)) return;

    String precioReferencial = this.view.getPrecioReferenciaField().getText();
    if(!validator.validatePrecioReferencia(precioReferencial)) return;

    List<Idioma> idiomas = this.view.getIdiomasList().getSelectedValuesList();
    if(!validator.validateIdiomas(idiomas)) return;

    List<Autor> autores = this.view.getAutoresList().getSelectedValuesList();
    if(!validator.validateAutores(autores)) return;

    List<Categoria> categorias = this.view.getCategoriasList().getSelectedValuesList();
    if(!validator.validateCategorias(categorias)) return;

    Editorial editorial = (Editorial) this.view.getEditorialCombo().getSelectedItem();
    if(!validator.validateEditorial(editorial)) return;
    // @formatter:on

    assert original != null;

    original.setSerie(serie);
    original.setIsbn(isbn);
    original.setTitulo(titulo);
    original.setNumeroPaginas(Integer.parseInt(numeroPaginas));
    original.setAnoPublicacion(Year.of(Integer.parseInt(anoPublicacion)));
    original.setPrecioReferencia(Integer.parseInt(precioReferencial));
    original.setIdiomas(new HashSet<>(idiomas));
    original.setAutores(new HashSet<>(autores));
    original.setCategorias(new HashSet<>(categorias));
    original.setEditorial(editorial);

    this.libroRepository.update(original);
    this.reload();
  }

  public void reload() {
    this.loadLibrosCombo();
    this.loadAutorList();
    this.loadCategoriasList();
    this.loadEditorialCombo();
    this.loadIdiomasList();
  }

  private void loadLibrosCombo() {
    List<Libro> libros = libroRepository.getAll();
    JComboBox<Libro> model = this.view.getLibroCombo();
    model.removeAllItems();
    for (Libro libro : libros) {
      model.addItem(libro);
    }
  }

  private void loadIdiomasList() {
    List<Idioma> idiomas = idiomaRepository.getAll();
    DefaultListModel<Idioma> model = this.view.getIdiomasModel();
    model.clear();
    for (Idioma idioma : idiomas) {
      model.addElement(idioma);
    }
  }

  private void loadCategoriasList() {
    List<Categoria> categorias = categoriaRepository.getAll();
    DefaultListModel<Categoria> model = this.view.getCategoriasModel();
    model.clear();
    for (Categoria categoria : categorias) {
      model.addElement(categoria);
    }
  }

  private void loadAutorList() {
    List<Autor> autores = autorRepository.getAll();
    DefaultListModel<Autor> model = this.view.getAutoresModel();
    model.clear();
    for (Autor autor : autores) {
      model.addElement(autor);
    }
  }

  private void loadEditorialCombo() {
    List<Editorial> editoriales = this.editorialRepository.getAll();
    JComboBox<Editorial> combobox = this.view.getEditorialCombo();
    combobox.removeAllItems();
    for (Editorial editorial : editoriales) {
      combobox.addItem(editorial);
    }
  }

  public LibroUpdatePanel getView() {
    return view;
  }
}
