package eu.dnetlib.client.adminpanel;

import com.github.gwtbootstrap.client.ui.*;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.ListBox;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
import com.github.gwtbootstrap.client.ui.constants.BackdropType;
import com.github.gwtbootstrap.client.ui.constants.ButtonType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.TimeZone;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.ui.Label;
import eu.dnetlib.espas.gui.client.FormFieldSet;
import eu.dnetlib.espas.gui.shared.DataProvider;
import eu.dnetlib.shared.HarvestScheduleInfo;

import java.util.Date;
import java.util.List;

/**
 * Created by stefania on 10/14/15.
 */
public class ScheduledHarvestFormModal {

    private Modal scheduledHarvestModal = new Modal();

    private FlowPanel manualHarvestFormPanel = new FlowPanel();

    private Alert errorLabel = new Alert();

    private Form manualHarvestForm = new Form();

    private ListBox dataProvidersListBox = new ListBox();
    private TextBox initialModificationDate = new TextBox();
    private TextBox cronExpression = new TextBox();

    private ObjectTypesWidget objectTypesWidget = new ObjectTypesWidget();

    private ModalFooter modalFooter = new ModalFooter();
    private FlowPanel actionButtons = new FlowPanel();
    private Button cancelButton = new Button();
    private Button saveButton = new Button();

    private DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    private TimeZone tz = TimeZone.createTimeZone(0);

    private ScheduledHarvestFormListener scheduledHarvestFormListener;

    private HarvestInfoServiceAsync harvestInfoService = GWT.create(HarvestInfoService.class);

    public ScheduledHarvestFormModal(final HarvestScheduleInfo harvestScheduleInfo, List<DataProvider> dataProviders) {

        if(harvestScheduleInfo!=null)
            scheduledHarvestModal.setTitle("Edit current schedule");
        else
            scheduledHarvestModal.setTitle("Add a new schedule");

        scheduledHarvestModal.add(manualHarvestFormPanel);

        errorLabel.setType(AlertType.ERROR);
        errorLabel.setVisible(false);
        errorLabel.setClose(false);
        manualHarvestFormPanel.add(errorLabel);

        manualHarvestFormPanel.add(manualHarvestForm);

        dataProvidersListBox.addItem("-- none selected --", "noneSelected");
        for(DataProvider dataProvider : dataProviders)
            dataProvidersListBox.addItem(dataProvider.getName(), dataProvider.getNamespace());
        dataProvidersListBox.setAlternateSize(AlternateSize.XXLARGE);
        manualHarvestForm.add(new FormFieldSet("Data Provider", dataProvidersListBox));

        Label initialModificationDateExample = new Label("e.g. " + dtf.format(new Date()));
        initialModificationDateExample.addStyleName("comment");
        initialModificationDateExample.addStyleName("fontItalic");

        initialModificationDate.setAlternateSize(AlternateSize.XXLARGE);
        initialModificationDate.addStyleName("inputWithComment");
        if(harvestScheduleInfo!=null)
            initialModificationDate.setEnabled(false);
        manualHarvestForm.add(new FormFieldSet("Initial Modification Date", initialModificationDate, initialModificationDateExample));

        Label cronExpressionExample = new Label("e.g. 0 15 10 ? * 6#3");
        cronExpressionExample.addStyleName("comment");
        cronExpressionExample.addStyleName("fontItalic");

        cronExpression.setAlternateSize(AlternateSize.XXLARGE);
        cronExpression.addStyleName("inputWithComment");
        manualHarvestForm.add(new FormFieldSet("Cron Expression", cronExpression, cronExpressionExample));

        objectTypesWidget.addStyleName("scheduledHarvestObjectTypes");
        manualHarvestForm.add(new FormFieldSet("Types", objectTypesWidget.asWidget()));

        actionButtons.addStyleName("confirmationModalButtons");

        modalFooter.add(actionButtons);
        scheduledHarvestModal.add(modalFooter);

        cancelButton.setText("Cancel");
        cancelButton.setType(ButtonType.DEFAULT);
        cancelButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                hide();
            }
        });
        actionButtons.add(cancelButton);

        if(harvestScheduleInfo!=null)
            saveButton.setText("Save changes");
        else
            saveButton.setText("Save");
        saveButton.setType(ButtonType.SUCCESS);
        saveButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {

                errorLabel.setVisible(false);

                boolean isInitialModificationDateValid = isInitialModificationDateValid();

                List<String> selectedTypes = objectTypesWidget.getSelectedTypes();

                if (isInitialModificationDateValid && !selectedTypes.isEmpty() && !dataProvidersListBox.getValue().equals("noneSelected")) {

                    if(harvestScheduleInfo!=null) {

                        harvestInfoService.updateHarvestSchedule(harvestScheduleInfo.getScheduleId(), objectTypesWidget.getSelectedTypes(),
                                "http://resources.espas-fp7.eu/provider/" + dataProvidersListBox.getValue(),
                                cronExpression.getValue(), new AsyncCallback<Void>() {

                                    @Override
                                    public void onFailure(Throwable caught) {

                                        errorLabel.setText("System error updating scheduled harvest");
                                        errorLabel.setVisible(true);
                                    }

                                    @Override
                                    public void onSuccess(Void result) {

                                        hide();
                                        if(scheduledHarvestFormListener!=null)
                                            scheduledHarvestFormListener.onSaved();
                                    }
                                });

                    } else {

                        harvestInfoService.scheduleHarvest(objectTypesWidget.getSelectedTypes(),
                                DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(initialModificationDate.getValue()),
                                "http://resources.espas-fp7.eu/provider/" + dataProvidersListBox.getValue(),
                                cronExpression.getValue(), new AsyncCallback<String>() {

                                    @Override
                                    public void onFailure(Throwable caught) {

                                        errorLabel.setText("System error saving new scheduled harvest");
                                        errorLabel.setVisible(true);
                                    }

                                    @Override
                                    public void onSuccess(String result) {

                                        hide();
                                        if(scheduledHarvestFormListener!=null)
                                            scheduledHarvestFormListener.onSaved();
                                    }
                                });

                    }

                } else {

                    if(initialModificationDate.getValue().trim().isEmpty() || cronExpression.getValue().trim().isEmpty()
                            || selectedTypes.isEmpty() || dataProvidersListBox.getValue().equals("noneSelected")) {
                        errorLabel.setText("All fields are required");
                        errorLabel.setVisible(true);
                    } else {
                        if(!isInitialModificationDateValid()) {
                            errorLabel.setText("Initial modification date is invalid");
                            errorLabel.setVisible(true);
                        }
                    }
                }
            }
        });
        actionButtons.add(saveButton);

        if(harvestScheduleInfo!=null)
            loadScheduledHarvest(harvestScheduleInfo);

        scheduledHarvestModal.addStyleName("formModal");
        scheduledHarvestModal.setAnimation(true);
        scheduledHarvestModal.setBackdrop(BackdropType.STATIC);
    }

    public void show() {
        scheduledHarvestModal.show();
    }

    public void hide() {
        scheduledHarvestModal.hide();
        scheduledHarvestModal.removeFromParent();
    }

    public interface ScheduledHarvestFormListener {
        void onSaved();
    }

    public void setScheduledHarvestFormListener(ScheduledHarvestFormListener scheduledHarvestFormListener) {
        this.scheduledHarvestFormListener = scheduledHarvestFormListener;
    }

    private void loadScheduledHarvest(HarvestScheduleInfo harvestScheduleInfo) {

        dataProvidersListBox.setSelectedValue(harvestScheduleInfo.getDataProviderId().split("http://resources.espas-fp7.eu/provider/")[1]);
        initialModificationDate.setValue(dtf.format(harvestScheduleInfo.getInitialModificationDate(), tz));
        cronExpression.setValue(harvestScheduleInfo.getCronExpression());
        objectTypesWidget.setSelectedTypes(harvestScheduleInfo.getTypes());
    }

    private boolean isInitialModificationDateValid() {

        try {
            DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(initialModificationDate.getValue());
        } catch (Exception exc) {
            return false;
        }

        return true;
    }
}
