package de.thpeetz.kontor.comics.views;

import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.data.provider.SortDirection;
import de.thpeetz.kontor.common.views.ColumnToggleContextMenu;
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.combobox.ComboBox;
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.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;

import de.thpeetz.kontor.comics.ComicConstants;
import de.thpeetz.kontor.comics.data.Comic;
import de.thpeetz.kontor.comics.data.Issue;
import de.thpeetz.kontor.comics.services.ComicService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.PermitAll;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@SpringComponent
@Scope("prototype")
@PermitAll
@Route(value = ComicConstants.ISSUE_ROUTE, layout = MainLayout.class)
@PageTitle("Issue | Comics | Kontor")
public class IssueView extends VerticalLayout {

    @Getter
    Grid<Issue> grid = new Grid<>(Issue.class, false);
    Grid.Column<Issue> idColumn = grid.addColumn(Issue::getId)
        .setHeader("ID").setResizable(true).setSortable(true);
    Grid.Column<Issue> createdColumn = grid.addColumn(Issue::getCreatedDate)
        .setHeader("Erstellt").setResizable(true).setSortable(true);
    Grid.Column<Issue> modifiedColumn = grid.addColumn(Issue::getLastModifiedDate)
        .setHeader("Geändert").setResizable(true).setSortable(true);
    Grid.Column<Issue> versionColumn = grid.addColumn(Issue::getVersion)
        .setHeader("Version").setResizable(true).setSortable(true);
    Grid.Column<Issue> titleColumn = grid.addColumn(Issue::getComicTitle)
        .setHeader("Comic").setResizable(true).setSortable(true);
    Grid.Column<Issue> volumeColumn = grid.addColumn(Issue::getVolumeName)
            .setHeader("Volume").setResizable(true).setSortable(true);
    Grid.Column<Issue> issueNumberColumn = grid.addColumn(Issue::getIssueNumber)
        .setHeader("Heft Nummer").setResizable(true).setSortable(true);
    Grid.Column<Issue> issueTitleColumn = grid.addColumn(Issue::getTitle)
            .setHeader("Full Title").setResizable(true).setSortable(true);
    Grid.Column<Issue> publishedOncolumn = grid.addColumn(Issue::getPublishedOn)
            .setHeader("Published").setResizable(true).setSortable(true);
    Grid.Column<Issue> isReadColumn = grid.addComponentColumn(issueColumn -> StatusIcon.create(issueColumn.getIsRead()))
        .setHeader("Gelesen?").setWidth("6rem").setSortable(true);
    Grid.Column<Issue> inStockColumn = grid.addComponentColumn(issueColumn -> StatusIcon.create(issueColumn.getInStock()))
        .setHeader("Im Bestand?").setWidth("6rem").setSortable(true);
    ComboBox<Comic> comicFilter = new ComboBox<>("Comic");
    @Getter
    IssueForm form;
    ComicService service;

    public IssueView(ComicService service) {
        this.service = service;
        addClassName("issue-view");
        setSizeFull();
        configureGrid();
        configureForm();

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

    private void configureGrid() {
        grid.addClassName("issue-grid");
        grid.setSizeFull();
        grid.getColumns().forEach(col -> col.setAutoWidth(true));
        idColumn.setVisible(false);
        createdColumn.setVisible(false);
        modifiedColumn.setVisible(false);
        versionColumn.setVisible(false);
        grid.setMultiSort(true);
        List<GridSortOrder<Issue>> sortOrder = new ArrayList<>();
        sortOrder.add(new GridSortOrder<Issue>(titleColumn, SortDirection.ASCENDING));
        sortOrder.add(new GridSortOrder<Issue>(issueNumberColumn, SortDirection.ASCENDING));
        grid.sort(sortOrder);
        grid.asSingleSelect().addValueChangeListener(event -> editIssue(event.getValue()));
    }

    private void configureForm() {
        form = new IssueForm(service.findAllComics(null), service.findAllVolumes());
        form.setWidth("25em");
        form.setVisible(false);
        form.addSaveListener(this::saveIssue);
        form.addDeleteListener(this::deleteIssue);
        form.addCloseListener(e -> 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() {
        comicFilter.setItems(service.findAllComics(null));
        comicFilter.setItemLabelGenerator(Comic::getTitle);
        comicFilter.setClearButtonVisible(true);
        comicFilter.addValueChangeListener(e -> updateList());

        Button addIssueButton = new Button("Add issue");
        addIssueButton.addClickListener(click -> addIssue());

        Button menuButton = new Button("Show/Hide Columns");
        menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        ColumnToggleContextMenu<Issue> columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton);
        columnToggleContextMenu.addColumnToggleItem(idColumn);
        columnToggleContextMenu.addColumnToggleItem(createdColumn);
        columnToggleContextMenu.addColumnToggleItem(modifiedColumn);
        columnToggleContextMenu.addColumnToggleItem(versionColumn);
        columnToggleContextMenu.addColumnToggleItem(titleColumn);
        columnToggleContextMenu.addColumnToggleItem(volumeColumn);
        columnToggleContextMenu.addColumnToggleItem(issueNumberColumn);
        columnToggleContextMenu.addColumnToggleItem(issueTitleColumn);
        columnToggleContextMenu.addColumnToggleItem(publishedOncolumn);
        columnToggleContextMenu.addColumnToggleItem(isReadColumn);
        columnToggleContextMenu.addColumnToggleItem(inStockColumn);
        HorizontalLayout toolbar = new HorizontalLayout(comicFilter, addIssueButton, menuButton);
        toolbar.addClassName("toolbar");
        return toolbar;
    }

    private void saveIssue(IssueForm.SaveEvent event) {
        service.saveIssue(event.getIssue());
        updateList();
        closeEditor();
    }

    private void deleteIssue(IssueForm.DeleteEvent event) {
        service.deleteIssue(event.getIssue());
        updateList();
        closeEditor();
    }

    public void editIssue(Issue issue) {
        if (issue == null) {
            closeEditor();
        } else {
            form.setIssue(issue);
            if (issue.getIssueWorks() == null) {
                log.info("No issue works");
            } else {
                log.info("Issue works sze: {}", issue.getIssueWorks().size());
            }
            form.setIssueWorks(issue.getIssueWorks());
            form.setVisible(true);
            addClassName("editing");
        }
    }

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

    private void addIssue() {
        grid.asSingleSelect().clear();
        editIssue(new Issue());
    }

    private void updateList() {
        grid.setItems(service.findAllIssuesForComic(comicFilter.getValue()));
    }
}
