/* 
 *  TableDataGUI.java
 * 
 *  Copyright 2016 Avaya Inc. All Rights Reserved.
 * 
 *  Usage of this source is bound to the terms described
 *  in AvayaLicenseSDK.rtf.
 * 
 *  Avaya - Confidential & Proprietary. Use pursuant to your signed agreement
 *  or Avaya Policy
 * 
 */
package com.avaya.ccs.javafxrefclient;

import java.util.ArrayList;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableView;

public abstract class TableDataGUI {

    private final Logger LOG;
    private final ObservableList<Data> items = FXCollections.observableArrayList();
    private final TableView<Data> itemSelection = new TableView<Data>();
    private DetailsForm detailsForm;

    public TableDataGUI(Logger LOG) {
        this.LOG = LOG;

        itemSelection.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
            String methodName = "itemSelectionChanged() ";
            if (newSelection != null) {
                LOG.trace(methodName + "+");
                redrawControls();
                LOG.trace(methodName + "-");
            } else {
                LOG.trace(methodName + "selection is null");
            }
        });
    }

    protected Data getCurrentItemSelection() {
        String methodName = "getCurrentItemSelection() ";
        Data currentSelection = (Data) getItemSelection().getSelectionModel().getSelectedItem();
        if (currentSelection != null) {
            LOG.trace(methodName + "returning non NULL");
            return currentSelection;
        } else {
            LOG.trace(methodName + "returning NULL");
            return null;
        }
    }

    protected void setSelectionToFirstElement() {
        getItemSelection().getSelectionModel().selectFirst();
    }

    protected List<Data> getAllItems() {
        return getItemSelection().getItems();
    }

    protected List<Data> getUnselectedItems() {
        List<Data> allItems = getAllItems();
        List<Data> unselectedItems = new ArrayList<>();
        unselectedItems.addAll(allItems);
        Data currentSelection = (Data) getItemSelection().getSelectionModel().getSelectedItem();
        if (currentSelection != null) {
            unselectedItems.remove(currentSelection);
        }
        return unselectedItems;
    }

    //This method is responsible for updating the gui with any new user related data
    public void update(ObservableList<Data> data) {
        String methodName = "update() ";
        LOG.trace(methodName + "new count =  " + data.size());
        items.clear();
        this.items.addAll(data);
        refreshListsAndRedraw();
    }

    //This version assumes only the new data object needs to be updated
    public void update(Data data) {
        String methodName = "update() ";
        LOG.trace(methodName + "DataID:" + data.getId());
        //Look in existing list of entry
        Data itemFound = null;
        for (Data item : this.items) {
            if (item.getId().equals(data.getId())) {
                // if there update it
                itemFound = item;
                break;
            }
        }
        if (itemFound != null) {
            LOG.trace(methodName + "existing entry found");
            if (data.isDeleted()) {
                LOG.trace(methodName + "update is a deletion update, removing from list");
                this.items.remove(itemFound);
            } else {
                LOG.trace(methodName + "updating entry");
                itemFound.update(data);
                itemSelection.refresh();
            }
        } else if (data.isDeleted()) {
            LOG.trace(methodName + "existing entry not found, but update is a delete so NOT adding");
        } else {
            LOG.trace(methodName + "existing entry not found, adding");
            this.items.add(data);
        }
        refreshListsAndRedraw();
    }

    public void clearData() {
        items.clear();
        refreshListsAndRedraw();
    }

    protected void refreshListsAndRedraw() {
        this.getDetailsForm().refresh();
        if (!getItems().isEmpty()) {
            if (getCurrentItemSelection() == null) {
                setSelectionToFirstElement();
            }
        }

        redrawControls();
    }

    public Data getItem(String id) {
        String methodName = "getItem() ";
        LOG.trace(methodName + "ID:" + id);
        for (Data item : this.items) {
            if (item.getId().equals(id)) {
                LOG.trace(methodName + "item found");
                return item;
            }
        }
        return null;
    }

    public ObservableList<Data> getItems() {
        return this.items;
    }

    //The implementing class implements this method which is responsible for redrawing the GUI elements
    protected abstract void redrawControls();

    public DetailsForm getDetailsForm() {
        return detailsForm;
    }

    public void setDetailsForm(DetailsForm detailsForm) {
        this.detailsForm = detailsForm;
    }

    /**
     * @return the itemSelection
     */
    public TableView<Data> getItemSelection() {
        return itemSelection;
    }
}
