package de.thpeetz.kontor.tysc.views;

import de.thpeetz.kontor.comics.data.Comic;
import de.thpeetz.kontor.common.views.StatusIcon;
import org.springframework.context.annotation.Scope;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;

import de.thpeetz.kontor.common.views.ColumnToggleContextMenu;
import de.thpeetz.kontor.common.views.MainLayout;
import de.thpeetz.kontor.tysc.TyscConstants;
import de.thpeetz.kontor.tysc.data.Card;
import de.thpeetz.kontor.tysc.services.CardService;
import jakarta.annotation.security.PermitAll;
import lombok.Getter;

@SpringComponent
@Scope("prototype")
@PermitAll
@Route(value = TyscConstants.CARD_ROUTE, layout = MainLayout.class)
@PageTitle("Card | Tysc | Kontor")
public class CardView extends VerticalLayout {

    @Getter
    Grid<Card> grid = new Grid<>(Card.class, false);
    Grid.Column<Card> idColumn = grid.addColumn(Card::getId).setHeader("ID")
            .setResizable(true).setSortable(true);
    Grid.Column<Card> createdColumn = grid.addColumn(Card::getCreatedDate)
            .setHeader("Erstellt").setResizable(true).setSortable(true);
    Grid.Column<Card> modifiedColumn = grid.addColumn(Card::getLastModifiedDate)
            .setHeader("Geändert").setResizable(true).setSortable(true);
    Grid.Column<Card> numberColumn = grid.addColumn(Card::getCardNumber)
            .setHeader("Nummer").setResizable(true).setSortable(true);
    Grid.Column<Card> yearColumn = grid.addColumn(Card::getYear)
            .setHeader("Jahr").setResizable(true).setSortable(true);
    Grid.Column<Card> vendorColumn = grid.addColumn(Card::getVendorName)
            .setHeader("Hersteller").setResizable(true).setSortable(true);
    Grid.Column<Card> cardSetColumn = grid.addColumn(Card::getCardSetName)
            .setHeader("Cardset").setResizable(true).setSortable(true);
    Grid.Column<Card> insertSetColumn = grid.addComponentColumn(card -> StatusIcon.create(card.getCardSet().isInsertSet()))
            .setHeader("Inserts").setWidth("6rem").setSortable(true);
    Grid.Column<Card> parallelSetColumn = grid.addComponentColumn(card -> StatusIcon.create(card.getCardSet().isParallelSet()))
            .setHeader("Parallels").setWidth("6rem").setSortable(true);
    Grid.Column<Card> playerColumn = grid.addColumn(Card::getPlayerName).setHeader("Spieler").setResizable(true).setSortable(true);
    TextField filterText = new TextField();
    @Getter
    CardForm form;
    CardService service;

    public CardView(CardService service) {
        this.service = service;
        addClassName("card-view");
        setSizeFull();
        configureGrid();
        configureForm();

        add(getToolbar(), getContent());
        updateList();
    }

    private void configureGrid() {
        grid.addClassName("card-grid");
        grid.setSizeFull();
        grid.getColumns().forEach(col -> col.setAutoWidth(true));
        grid.asSingleSelect().addValueChangeListener(event -> editCard(event.getValue()));
        idColumn.setVisible(false);
        createdColumn.setVisible(false);
        modifiedColumn.setVisible(false);
    }

    private void configureForm() {
        form = new CardForm(service.findAllVendors(null));
        form.setWidth("25em");
        form.setVisible(false);
        form.addSaveListener(this::saveCard);
        form.addDeleteListener(this::deleteCard);
        form.addCloseListener(e -> closeEditor());
    }

    private void saveCard(CardForm.SaveEvent event) {
        service.saveCard(event.getCard());
        updateList();
        closeEditor();
    }

    private void deleteCard(CardForm.DeleteEvent event) {
        service.deleteCard(event.getCard());
        updateList();
        closeEditor();
    }

    private Component getContent() {
        HorizontalLayout content = new HorizontalLayout(grid, form);
        content.setFlexGrow(2, grid);
        content.setFlexGrow(1, form);
        content.addClassName("content");
        content.setSizeFull();
        return content;
    }

    private HorizontalLayout getToolbar() {
        filterText.setPlaceholder("Filter by name...");
        filterText.setClearButtonVisible(true);
        filterText.setValueChangeMode(ValueChangeMode.LAZY);
        filterText.addValueChangeListener(e -> updateList());

        Button addCardButton = new Button("Add card");
        addCardButton.addClickListener(click -> addCard());

        Button menuButton = new Button("Show/Hide Columns");
        menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        ColumnToggleContextMenu<Card> columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton);
        columnToggleContextMenu.addColumnToggleItem(idColumn);
        columnToggleContextMenu.addColumnToggleItem(createdColumn);
        columnToggleContextMenu.addColumnToggleItem(modifiedColumn);
        columnToggleContextMenu.addColumnToggleItem(numberColumn);
        columnToggleContextMenu.addColumnToggleItem(yearColumn);
        columnToggleContextMenu.addColumnToggleItem(vendorColumn);
        columnToggleContextMenu.addColumnToggleItem(cardSetColumn);
        columnToggleContextMenu.addColumnToggleItem(insertSetColumn);
        columnToggleContextMenu.addColumnToggleItem(parallelSetColumn);
        columnToggleContextMenu.addColumnToggleItem(playerColumn);
        HorizontalLayout toolbar = new HorizontalLayout(filterText, addCardButton, menuButton);
        toolbar.addClassName("toolbar");
        return toolbar;
    }

    public void editCard(Card card) {
        if (card == null) {
            closeEditor();
        } else {
            form.setCard(card);
            form.setVisible(true);
            addClassName("editing");
        }
    }

    private void closeEditor() {
        form.setCard(null);
        form.setVisible(false);
        removeClassName("editing");
    }

    private void addCard() {
        grid.asSingleSelect().clear();
        editCard(new Card());
    }

    public void updateList() {
        grid.setItems(service.findAllCards(filterText.getValue()));
    }
}
