package de.thpeetz.kontor.comics.views;

import java.util.List;

import com.vaadin.flow.component.ComponentEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder;

import de.thpeetz.kontor.comics.data.Artist;
import de.thpeetz.kontor.comics.data.Comic;
import de.thpeetz.kontor.comics.data.IssueWork;
import de.thpeetz.kontor.comics.data.Worktype;
import de.thpeetz.kontor.common.views.ComicIssueField;

public class IssueWorkForm extends FormLayout {
    ComicIssueField issue = new ComicIssueField("Issue");
    ComboBox<Artist> artist = new ComboBox<>("Artist");
    ComboBox<Worktype> workType = new ComboBox<>("Worktype");

    Button save = new Button("Save");
    Button delete = new Button("Delete");
    Button close = new Button("Cancel");

    Binder<IssueWork> binder = new BeanValidationBinder<>(IssueWork.class);

    public IssueWorkForm(List<Comic> comics, List<Artist> artists, List<Worktype> workTypes) {
        addClassName("issuework-form");
        binder.bindInstanceFields(this);

        issue.setComics(comics);
        //issue.setItems(issues);
        //issue.setItemLabelGenerator(Issue::getIssueNumber);
        artist.setItems(artists);
        artist.setItemLabelGenerator(Artist::getName);
        workType.setItems(workTypes);
        workType.setItemLabelGenerator(Worktype::getName);
        add(issue, artist, workType, createButtonsLayout());
    }

    private HorizontalLayout createButtonsLayout() {
        save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        delete.addThemeVariants(ButtonVariant.LUMO_ERROR);
        close.addThemeVariants(ButtonVariant.LUMO_TERTIARY);

        save.addClickShortcut(Key.ENTER);
        close.addClickShortcut(Key.ESCAPE);

        save.addClickListener(event -> validateAndSave());
        delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean())));
        close.addClickListener(event -> fireEvent(new CloseEvent(this)));

        binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
        return new HorizontalLayout(save, delete, close);
    }

    private void validateAndSave() {
        if (binder.isValid()) {
            fireEvent(new SaveEvent(this, binder.getBean()));
        }
    }

    public void setIssueWork(IssueWork issueWork) {
        binder.setBean(issueWork);
    }

    public abstract static class IssueWorkFormEvent extends ComponentEvent<IssueWorkForm> {
        private IssueWork issueWork;

        protected IssueWorkFormEvent(IssueWorkForm source, IssueWork issueWork) {
            super(source, false);
            this.issueWork = issueWork;
        }

        public IssueWork getIssueWork() {
            return issueWork;
        }
    }

    public static class SaveEvent extends IssueWorkFormEvent {
        SaveEvent(IssueWorkForm source, IssueWork issueWork) {
            super(source, issueWork);
        }
    }

    public static class DeleteEvent extends IssueWorkFormEvent {
        DeleteEvent(IssueWorkForm source, IssueWork issueWork) {
            super(source, issueWork);
        }
    }

    public static class CloseEvent extends IssueWorkFormEvent {
        CloseEvent(IssueWorkForm source) {
            super(source, null);
        }
    }

    public void addDeleteListener(ComponentEventListener<DeleteEvent> listener) {
        addListener(DeleteEvent.class, listener);
    }

    public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
        addListener(SaveEvent.class, listener);
    }

    public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
        addListener(CloseEvent.class, listener);
    }
}
