import java.util.concurrent.atomic.AtomicLong;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableView.TableViewSelectionModel;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MemoryLeakVirtualFlow extends Application {

	public static final boolean TURN_ON_WORKAROUND = false;

	static class Item {

		private final ReadOnlyObjectProperty<Long> id;

		public Item(final long id) {
			this.id = new SimpleObjectProperty<>(id);
		}

		public ReadOnlyObjectProperty<Long> idProperty() {
			return id;
		}
	}

	@Override
	public void start(final Stage stage) throws Exception {
		Platform.accessibilityActiveProperty()
				.addListener((obs, prevActive, active) -> showAccessibilityStatus(active));
		showAccessibilityStatus(Platform.isAccessibilityActive());

		final Scene scene = new Scene(createRoot(), 200, 200);
		stage.setScene(scene);
		stage.show();
	}

	private final ObservableList<Item> items = FXCollections.observableArrayList();
	private final AtomicLong counter = new AtomicLong();

	private Parent createRoot() {
		final TableView<Item> tableView = createTableView();

		final Button addButton = new Button("Add");
		addButton.setOnAction(eh -> {
			items.add(0, new Item(counter.incrementAndGet()));

			final TableViewSelectionModel<Item> sm = tableView.getSelectionModel();
			if (sm.getSelectedItems().isEmpty()) {
				sm.selectLast();
			}
			if (!tableView.isFocused()) {
				tableView.requestFocus();
			}
		});

		final Button clearButton = new Button("Clear");
		clearButton.setOnAction(eh -> items.clear());

		return new VBox(5.0, new HBox(5.0, addButton, clearButton), tableView);
	}

	private TableView<Item> createTableView() {
		final TableView<Item> tableView = new TableView<>(items);

		final TableColumn<Item, Long> idColumn = new TableColumn<>();
		idColumn.setCellValueFactory(cd -> cd.getValue().idProperty());

		tableView.getColumns().add(idColumn);
		return tableView;
	}

	private void showAccessibilityStatus(final boolean active) {
		if (active) {
			System.out.println("Accessibility turned on");
		} else {
			System.out.println("Accessibility turned off");
		}
	}

	public static void main(final String[] args) {
		if (TURN_ON_WORKAROUND) {
			System.setProperty("glass.accessible.force", "false");
		}

		launch(args);
	}
}