package de.thpeetz.kontor.media.views;

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.checkbox.Checkbox;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder;
import de.thpeetz.kontor.media.data.MediaActorFile;
import de.thpeetz.kontor.media.data.MediaFile;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class MediaFileForm extends FormLayout {

    TextField id = new TextField("ID");
    TextField url = new TextField("URL");
    TextField title = new TextField("Title");
    TextField fileName = new TextField("Dateiname");
    TextField cloudLink = new TextField("Cloud Link");
    Checkbox review = new Checkbox("Review");
    Checkbox shouldDownload = new Checkbox("Download");
    Grid<MediaActorFile> mediaActorFiles = new Grid<>(MediaActorFile.class);

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

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

    public MediaFileForm() {
        addClassName("mediafile-form");
        binder.bindInstanceFields(this);
        id.setReadOnly(true);

        mediaActorFiles.setColumns("media_actor.name");
        mediaActorFiles.getColumnByKey("media_actor.name").setHeader("Actor");

        add(id, 2);
        add(url, 2);
        add(title, 2);
        add(fileName, 2);
        add(cloudLink, 2);
        add(review, shouldDownload);
        add(mediaActorFiles, 2);
        add(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(event -> save.setEnabled(event.getBinder().isValid()));
        return new HorizontalLayout(save, delete, close);
    }

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

    public void setMediaFile(MediaFile mediaFile) {
        binder.setBean(mediaFile);
    }

    public void setMediaActorFiles(List<MediaActorFile> actorFiles) {
        mediaActorFiles.setItems(actorFiles);
    }

    @Getter
    public abstract static class MediaFileFormEvent extends ComponentEvent<MediaFileForm> {
        private final MediaFile mediaFile;

        protected MediaFileFormEvent(MediaFileForm source, MediaFile mediaFile) {
            super(source, false);
            this.mediaFile = mediaFile;
        }

    }

    public static class SaveEvent extends MediaFileFormEvent {
        SaveEvent(MediaFileForm source, MediaFile mediaFile) {
            super(source, mediaFile);
        }
    }

    public static class DeleteEvent extends MediaFileFormEvent {
        DeleteEvent(MediaFileForm source, MediaFile mediaFile) {
            super(source, mediaFile);
        }
    }

    public static class CloseEvent extends MediaFileFormEvent {
        CloseEvent(MediaFileForm 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);
    }
}
