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.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.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
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.query.client.Function;
import com.google.gwt.user.client.Event;
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.client.Admin;
import eu.dnetlib.client.AdminWidget;
import eu.dnetlib.espas.gui.client.user.DataProviderAccessService;
import eu.dnetlib.espas.gui.client.user.DataProviderAccessServiceAsync;
import eu.dnetlib.espas.gui.shared.DataProvider;
import eu.dnetlib.shared.HarvestHistoryInfo;

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

import static com.google.gwt.query.client.GQuery.$;

/**
 * Created by stefania on 6/17/14.
 */
public class HarvestHistoryWidget implements AdminWidget {

    private static HarvestHistoryWidget instance = null;

    private FlowPanel manageHarvestHistoryPanel = new FlowPanel();

    private Alert errorAlert = new Alert();
    private Alert successAlert = new Alert();
    private Alert warningAlert = new Alert();

    private FlowPanel pageControlsPanel = new FlowPanel();
    private FlowPanel harvestHistoryPanel = new FlowPanel();

    private ListBox dataProvidersListBox = new ListBox();

    private List<DataProvider> dataProviderList = new ArrayList<DataProvider>();

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

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

    private HarvestHistoryWidget() {

        manageHarvestHistoryPanel.addStyleName("contentPanel");

        errorAlert.setType(AlertType.ERROR);
        errorAlert.setVisible(false);
        errorAlert.setClose(false);
        manageHarvestHistoryPanel.add(errorAlert);

        successAlert.setType(AlertType.SUCCESS);
        successAlert.setVisible(false);
        successAlert.setClose(false);
        manageHarvestHistoryPanel.add(successAlert);

        warningAlert.setType(AlertType.WARNING);
        warningAlert.setVisible(false);
        warningAlert.setClose(false);
        manageHarvestHistoryPanel.add(warningAlert);

        manageHarvestHistoryPanel.add(pageControlsPanel);
        manageHarvestHistoryPanel.add(harvestHistoryPanel);

        pageControlsPanel.addStyleName("row");
        pageControlsPanel.addStyleName("page-controls");
    }

    public static final HarvestHistoryWidget getInstance() {

        if(instance==null)
            instance = new HarvestHistoryWidget();

        return instance;
    }

    @Override
    public void clear() {

        errorAlert.setVisible(false);
        successAlert.setVisible(false);
        warningAlert.setVisible(false);

        harvestHistoryPanel.clear();
        pageControlsPanel.clear();

        dataProviderList.clear();
        dataProvidersListBox.clear();
    }

    @Override
    public void reload() {

        Admin.menuBar.clear();

        Admin.menuBar.add(new HTML("<div class=\"sidebar-toggler visible-xs\"><i class=\"ion-navicon\"></i></div>"));
        Admin.menuBar.add(new HTML("<div class=\"page-title\" id=\"pageTitle\">Harvest History<small class=\"hidden-xs hidden-sm\">" +
                "<strong>Always showing the last 30 entries in the harvest history!</strong></small></div>"));

        dataProviderAccessService.getDataProviders(new AsyncCallback<List<DataProvider>>() {

            @Override
            public void onFailure(Throwable arg0) {

            }

            @Override
            public void onSuccess(List<DataProvider> dataProviders) {

                dataProviderList.addAll(dataProviders);
                updateHistoryOfHarvests(true, null, null);
                updateControls();
            }
        });
    }

    private void updateHistoryOfHarvests(final boolean clearAlerts, final String successMessage, String providerId) {

        final HTML loadingWheel = new HTML("<div class=\"loader-big\"></div><div class=\"whiteFilm\"></div>");
        manageHarvestHistoryPanel.addStyleName("loading-big");
        manageHarvestHistoryPanel.add(loadingWheel);

        harvestInfoService.getHarvestHistory(providerId, new AsyncCallback<List<HarvestHistoryInfo>>() {

            @Override
            public void onFailure(Throwable caught) {

                manageHarvestHistoryPanel.removeStyleName("loading-big");
                manageHarvestHistoryPanel.remove(loadingWheel);

                successAlert.setVisible(false);
                warningAlert.setVisible(false);

                errorAlert.setText("System error retrieving harvest history");
                errorAlert.setVisible(true);
            }

            @Override
            public void onSuccess(List<HarvestHistoryInfo> harvestHistoryInfoList) {

                if(clearAlerts) {
                    errorAlert.setVisible(false);
                    successAlert.setVisible(false);
                    warningAlert.setVisible(false);
                }

                if(successMessage!=null) {
                    successAlert.setText(successMessage);
                    successAlert.setVisible(true);
                }

                manageHarvestHistoryPanel.removeStyleName("loading-big");
                manageHarvestHistoryPanel.remove(loadingWheel);

                updateContents(harvestHistoryInfoList);
            }
        });
    }

    @Override
    public void setToken(String token) {

    }

    @Override
    public void afterAdditionToRootPanel() {

    }

    public void updateControls() {

        pageControlsPanel.clear();

        FlowPanel filters = new FlowPanel();
        filters.addStyleName("col-md-12");
        filters.addStyleName("filters");

        pageControlsPanel.add(filters);

        FlowPanel links = new FlowPanel();
        links.addStyleName("links");

        filters.add(links);

        Label filterLabel = new Label("Filter harvests by data provider:");
        filterLabel.addStyleName("filterLabel");
        links.add(filterLabel);

        dataProvidersListBox.addItem("-- none selected --", "noneSelected");
        for(DataProvider dataProvider : dataProviderList)
            dataProvidersListBox.addItem(dataProvider.getName(), dataProvider.getNamespace());
        dataProvidersListBox.setAlternateSize(AlternateSize.XXLARGE);
        dataProvidersListBox.addChangeHandler(new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent event) {

                if(dataProvidersListBox.getValue().equals("noneSelected"))
                    updateHistoryOfHarvests(true, null, null);
                else
                    updateHistoryOfHarvests(true, null, "http://resources.espas-fp7.eu/provider/" + dataProvidersListBox.getValue());
            }
        });
        links.add(dataProvidersListBox);

        FlowPanel actions = new FlowPanel();
        actions.addStyleName("show-options");

        filters.add(actions);

        DropdownButton bulkActions = new DropdownButton();
        bulkActions.setText("Bulk Actions");
        bulkActions.setType(ButtonType.DEFAULT);

        NavLink deleteButton = new NavLink("Delete");
        deleteButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {

                errorAlert.setVisible(false);
                successAlert.setVisible(false);
                warningAlert.setVisible(false);

                List<String> historyIds = getCheckedHistories();

                if(!historyIds.isEmpty()) {
                    delete(historyIds);
                } else {
                    warningAlert.setText("You haven't selected any harvest history");
                    warningAlert.setVisible(true);
                }
            }
        });
        bulkActions.add(deleteButton);

        actions.add(bulkActions);
    }

    public void updateContents(List<HarvestHistoryInfo> harvestHistoryList) {

        harvestHistoryPanel.clear();

        String contents = "<div class=\"row users-list\">";
        contents += "<div class=\"col-md-12\">";

        contents += "<div class=\"row headers\">" +
                "<div class=\"col-sm-1 header select-users\">" +
                "<input id=\"allHistoriesCheckbox\" type=\"checkbox\">" +
                "</div>" +
                "<div class=\"col-sm-2 header hidden-xs\">" +
                "<label><a href=\"#\">Start Date</a></label>" +
                "</div>" +
                "<div class=\"col-sm-2 header hidden-xs\">" +
                "<label><a href=\"#\">End Date</a></label>" +
                "</div>" +
                "<div class=\"col-sm-3 header hidden-xs\">" +
                "<label><a href=\"#\">Type(s)</a></label>" +
                "</div>" +
                "<div class=\"col-sm-2 header hidden-xs\">" +
                "<label><a href=\"#\"># of records harvested</a></label>" +
                "</div>" +
                "<div class=\"col-sm-1 header hidden-xs\">" +
                "<label><a href=\"#\"># of errors</a></label>" +
                "</div>" +
                "<div class=\"col-sm-1 header hidden-xs\">" +
                "<label><a href=\"#\">Delete</a></label>" +
                "</div>" +
                "</div>";

        if(harvestHistoryList.size()==0) {

            contents += "<div class=\"row user\">" +
                    "<div class=\"col-md-12\"><div class=\"alert alert-warning\">No harvest history found</div></div>" +
                    "</div>";

        } else {

            for(HarvestHistoryInfo harvestHistoryInfo : harvestHistoryList) {

                contents += "<div class=\"row user\">" +
                        "<div class=\"col-sm-1 avatar\"><input id=\"" + harvestHistoryInfo.getHarvestId() + "#checkBox\" class=\"checkBox\" type=\"checkbox\" name=\"select-user\">" +
                        "<span class=\"namespace\">" + harvestHistoryInfo.getDataProviderId().split("http://resources.espas-fp7.eu/provider/")[1] + "</span></div>" +
                        "<div class=\"col-sm-2\"><div class=\"startDate\" href=\"#\">" + dtf.format(harvestHistoryInfo.getStartDate(), tz) + "</div></div>" +
                        "<div class=\"col-sm-2\"><div class=\"endDate\" href=\"#\">" + dtf.format(harvestHistoryInfo.getFinishDate(), tz) + "</div></div>";

                String types= "";
                for(int i=0; i<harvestHistoryInfo.getTypes().size(); i++) {
                    if(i!=0)
                        types += ", ";
                    types += harvestHistoryInfo.getTypes().get(i);
                }

                contents += "<div class=\"col-sm-3\"><div class=\"types\" href=\"#\">" + types + "</div></div>" +
                        "<div class=\"col-sm-2\"><div class=\"recordCount\" href=\"#\">" + harvestHistoryInfo.getRecordCount() + "</div></div>" +
                        "<div class=\"col-sm-1\"><div class=\"errorCount\" href=\"#\">" + harvestHistoryInfo.getErrors().size() + "</div></div>" +
                        "<div class=\"col-sm-1\"><div class=\"actions\" href=\"#\"><input id=\"" + harvestHistoryInfo.getHarvestId() + "#delete\" " +
                        "type=\"image\" title=\"Delete\" src=\"imgs/icn_trash.png\" class=\"delete\"></div></div>" +
                        "</div>";
            }
        }

        contents += "</div>";
        contents += "</div>";

        HTML usersList = new HTML();
        usersList.setHTML(contents);

        harvestHistoryPanel.add(usersList);

        addWidgetHandlers();
    }

    @Override
    public Widget asWidget() {
        return manageHarvestHistoryPanel;
    }

    private List<String> getCheckedHistories() {

        List<String> historyIds = new ArrayList<String>();

        NodeList<Element> checkBoxes = $(".checkBox").get();
        for(int i=0; i<checkBoxes.getLength(); i++) {
            InputElement checkBox = (InputElement) checkBoxes.getItem(i);
            if(checkBox.isChecked()) {
                String[] idParts = checkBox.getId().split("#");
                historyIds.add(idParts[0]);
            }
        }

        return historyIds;
    }

    public void addWidgetHandlers() {

        $("#allHistoriesCheckbox").click(new Function() {

            public boolean f(Event e) {

                InputElement allHistories = (InputElement) Document.get().getElementById("allHistoriesCheckbox");

                NodeList<Element> checkBoxes = $(".checkBox").get();

                if(allHistories.isChecked()) {
                    for(int i=0; i<checkBoxes.getLength(); i++) {
                        InputElement checkBox = (InputElement) checkBoxes.getItem(i);
                        checkBox.setChecked(true);
                    }
                } else {
                    for(int i=0; i<checkBoxes.getLength(); i++) {
                        InputElement checkBox = (InputElement) checkBoxes.getItem(i);
                        checkBox.setChecked(false);
                    }
                }

                return true;
            }
        });

        $(".delete").click(new Function() {

            public boolean f(Event e) {

                errorAlert.setVisible(false);
                successAlert.setVisible(false);
                warningAlert.setVisible(false);

                String[] idParts = $(e).get(0).getId().split("#");
                List<String> harvestIds = new ArrayList<String>();
                harvestIds.add(idParts[0]);

                delete(harvestIds);

                return true;
            }
        });
    }

    private void delete(final List<String> harvestIds) {

        final Modal deleteConfirmationPopup = new Modal();

        deleteConfirmationPopup.addStyleName("confirmationModal");
        deleteConfirmationPopup.setAnimation(true);
        deleteConfirmationPopup.setBackdrop(BackdropType.STATIC);

        deleteConfirmationPopup.setTitle("Delete Confirmation");

        HTML message = new HTML("Are you sure you want to delete the selected harvest history item(s)?");
        deleteConfirmationPopup.add(message);

        FlowPanel actionButtons = new FlowPanel();
        actionButtons.addStyleName("confirmationModalButtons");

        ModalFooter modalFooter = new ModalFooter();
        modalFooter.add(actionButtons);
        deleteConfirmationPopup.add(modalFooter);

        Button no = new Button("Cancel");
        no.setType(ButtonType.DEFAULT);
        no.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                deleteConfirmationPopup.hide();
                deleteConfirmationPopup.removeFromParent();
            }
        });
        actionButtons.add(no);

        Button yes = new Button("Yes, delete them");
        yes.setType(ButtonType.DANGER);
        yes.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {

                deleteConfirmationPopup.hide();
                deleteConfirmationPopup.removeFromParent();

                final HTML loadingWheel = new HTML("<div class=\"loader-big\"></div><div class=\"whiteFilm\"></div>");
                manageHarvestHistoryPanel.addStyleName("loading-big");
                manageHarvestHistoryPanel.add(loadingWheel);

                harvestInfoService.deleteHarvestHistory(harvestIds, new AsyncCallback<Void>() {

                    @Override
                    public void onFailure(Throwable throwable) {

                        manageHarvestHistoryPanel.removeStyleName("loading-big");
                        manageHarvestHistoryPanel.remove(loadingWheel);

                        errorAlert.setText("Failed to delete the selected harvest history item(s)");
                        errorAlert.setVisible(true);
                    }

                    @Override
                    public void onSuccess(Void aVoid) {

                        manageHarvestHistoryPanel.removeStyleName("loading-big");
                        manageHarvestHistoryPanel.remove(loadingWheel);

                        updateHistoryOfHarvests(false, "Harvest history item(s) deleted successfully", "http://resources.espas-fp7.eu/provider/" + dataProvidersListBox.getValue());
                        AdminPanelController.getInstance().updateNoOfActions();
                    }
                });
            }
        });
        actionButtons.add(yes);

        deleteConfirmationPopup.show();
    }
}
