/**
   * Build a column representing an instance of the Object class. The object is represented by its
   * toString result.
   *
   * @param name label of the column
   * @param propertyName name of the property which is bound to the column
   * @param columnCount number of columns
   * @return a column of name name, bound with the property propertyName and with intelligent size
   */
  @Override
  public TableColumn buildColumn(String name, String propertyName, int columnCount) {
    TableColumn column = new TableColumn(name);
    column.setCellValueFactory(new PropertyValueFactory(propertyName));
    column.prefWidthProperty().bind(owner.widthProperty().divide(columnCount));
    column.setCellFactory(
        new Callback<TableColumn<E, C>, TableCell<E, C>>() {

          @Override
          public TableCell<E, C> call(TableColumn<E, C> p) {
            TableCell<E, C> cell =
                new TableCell<E, C>() {

                  @Override
                  protected void updateItem(C t, boolean bln) {
                    if (t != null) {
                      Text text = new Text(t.toString());
                      setGraphic(text);
                    }
                  }
                };
            return cell;
          }
        });
    return column;
  }
  public FileInfoTablePanel() {
    tableItems = FXCollections.observableArrayList();

    tableView = new TableView<>(tableItems);

    final TableColumn<FileInfoPath, String> col0 = new TableColumn<>("Name");
    col0.setCellValueFactory(
        p -> new ReadOnlyObjectWrapper<>(p.getValue().getFileInfo().getFilename()));
    col0.prefWidthProperty().bind(tableView.widthProperty().multiply(0.3));
    tableView.getColumns().add(col0);

    final TableColumn<FileInfoPath, String> col1 = new TableColumn<>("Path");
    col1.setCellValueFactory(p -> new ReadOnlyObjectWrapper<>(p.getValue().getPath()));
    col1.prefWidthProperty().bind(tableView.widthProperty().multiply(0.6));
    tableView.getColumns().add(col1);

    final TableColumn<FileInfoPath, String> col2 = new TableColumn<>("Size");
    col2.setCellValueFactory(
        p ->
            new ReadOnlyObjectWrapper<>(
                BackupUtil.humanReadableByteCount(p.getValue().getFileInfo().getSize())));
    col2.prefWidthProperty().bind(tableView.widthProperty().multiply(0.1));
    tableView.getColumns().add(col2);

    final TableColumn<FileInfoPath, String> col3 = new TableColumn<>("Alg");
    col3.setCellValueFactory(
        p -> new ReadOnlyObjectWrapper<>(p.getValue().getFileInfo().getDigestAlg().name()));
    col3.prefWidthProperty().bind(tableView.widthProperty().multiply(0.1));
    tableView.getColumns().add(col3);

    final TableColumn<FileInfoPath, String> col4 = new TableColumn<>("Digest");
    col4.setCellValueFactory(
        p -> new ReadOnlyObjectWrapper<>(p.getValue().getFileInfo().getDigest()));
    col4.prefWidthProperty().bind(tableView.widthProperty().multiply(0.2));
    tableView.getColumns().add(col4);

    final TableColumn<FileInfoPath, String> col5 = new TableColumn<>("Timestamp");
    col5.setCellValueFactory(
        p -> new ReadOnlyObjectWrapper<>(p.getValue().getFileInfo().getLastModifiedStr()));
    col5.prefWidthProperty().bind(tableView.widthProperty().multiply(0.2));
    tableView.getColumns().add(col5);

    final TableColumn<FileInfoPath, Integer> col6 = new TableColumn<>("Path Len");
    col6.setCellValueFactory(p -> new ReadOnlyObjectWrapper<>(p.getValue().getPath().length()));
    col6.prefWidthProperty().bind(tableView.widthProperty().multiply(0.1));
    tableView.getColumns().add(col6);

    tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    // pathList.setVisibleRowCount(4);
    tableView.setPrefHeight(100);

    label = new Label();

    final ScrollPane scrollPane = GuiUtils.createScrollPane(tableView);

    setCenter(scrollPane);
    setBottom(label);

    setFileInfo(null, null);
  }
  private TableView<Teilnehmer> initGUItabelle() {
    tabelle = new TableView<Teilnehmer>();

    TableColumn<Teilnehmer, Boolean> x = new TableColumn<Teilnehmer, Boolean>("");
    TableColumn<Teilnehmer, Integer> id = new TableColumn<Teilnehmer, Integer>("ID");
    TableColumn<Teilnehmer, String> projekt1 = new TableColumn<Teilnehmer, String>("Projekt 1");
    TableColumn<Teilnehmer, String> projekt2 = new TableColumn<Teilnehmer, String>("Projekt 2");
    TableColumn<Teilnehmer, String> status = new TableColumn<Teilnehmer, String>("Status");
    TableColumn<Teilnehmer, String> art = new TableColumn<Teilnehmer, String>("Art");

    x.prefWidthProperty().bind(tabelle.widthProperty().divide(14));
    id.prefWidthProperty().bind(tabelle.widthProperty().divide(14));
    projekt1.prefWidthProperty().bind(tabelle.widthProperty().divide(14).multiply(3));
    projekt2.prefWidthProperty().bind(tabelle.widthProperty().divide(14).multiply(3));
    status.prefWidthProperty().bind(tabelle.widthProperty().divide(14).multiply(3));
    art.prefWidthProperty().bind(tabelle.widthProperty().divide(14).multiply(3));

    x.setEditable(false);
    id.setEditable(false);
    projekt1.setEditable(false);
    projekt2.setEditable(false);
    status.setEditable(false);
    art.setEditable(false);

    tabelle.getColumns().add(x);
    tabelle.getColumns().add(id);
    tabelle.getColumns().add(projekt1);
    tabelle.getColumns().add(projekt2);
    tabelle.getColumns().add(status);
    tabelle.getColumns().add(art);

    return tabelle;
  }
  @FXML
  private void initialize() {
    ideaCategoryColumn.setCellValueFactory(cellData -> cellData.getValue().categoryProperty());
    ideaNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
    ideaStatusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());

    ideasTable
        .getSelectionModel()
        .selectedItemProperty()
        .addListener((observable, oldValue, newValue) -> showIdea(newValue));

    int divider = 3; // amount of column to divide equal

    ideaCategoryColumn.prefWidthProperty().bind(ideasTable.widthProperty().divide(divider));

    ideaArea.setEditable(false);
    ideaArea.setWrapText(true);

    new Thread(
            new Runnable() {

              @Override
              public void run() {

                IdeaDaoImpl ideaDaoImpl = new IdeaDaoImpl();
                ideaDaoImpl.createConnection();
                ideasList.addAll(ideaDaoImpl.getAllIdeasList());
                ideaDaoImpl.closeConnection();

                Platform.runLater(
                    new Runnable() {

                      @Override
                      public void run() {

                        ideasTable.setItems(ideasList);
                      }
                    });
              }
            })
        .start();
  }
  @FXML
  void initialize() {
    assert claimTasksButton != null
        : "fx:id=\"claimTasksButton\" was not injected: check your FXML file 'WorkflowInbox.fxml'.";
    assert synchronizeButton != null
        : "fx:id=\"synchronizeButton\" was not injected: check your FXML file 'WorkflowInbox.fxml'.";
    assert userName != null
        : "fx:id=\"userName\" was not injected: check your FXML file 'WorkflowInbox.fxml'.";
    assert taskTable != null
        : "fx:id=\"taskTable\" was not injected: check your FXML file 'WorkflowInbox.fxml'.";

    userName.setText(user);

    taskTable.setTableMenuButtonVisible(true);

    // BEGIN Task name
    TableColumn<LocalTask, String> tCol = new TableColumn<>();
    tCol.setText("Task");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getName());
        });
    taskTable.getColumns().add(tCol);
    // END Task name

    // BEGIN Task id
    tCol = new TableColumn<>();
    tCol.setText("id");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getId() + "");
        });
    taskTable.getColumns().add(tCol);
    // END Task id

    // BEGIN Component name
    tCol = new TableColumn<>();
    tCol.setText("Component");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getComponentName());
        });
    taskTable.getColumns().add(tCol);
    // END Component name

    // BEGIN WorkflowAction
    tCol = new TableColumn<>();
    tCol.setText("Action");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getAction().toString());
        });
    tCol.setVisible(false);
    taskTable.getColumns().add(tCol);
    // END WorkflowAction

    // BEGIN TaskActionStatus
    tCol = new TableColumn<>();
    tCol.setText("Action Status");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getActionStatus().name());
        });
    tCol.setVisible(false);
    taskTable.getColumns().add(tCol);
    // END TaskActionStatus

    // BEGIN Owner
    tCol = new TableColumn<>();
    tCol.setText("Owner");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getOwner());
        });
    tCol.setVisible(false);
    taskTable.getColumns().add(tCol);
    // END Owner

    // BEGIN Status
    tCol = new TableColumn<>();
    tCol.setText("Status");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getStatus().name());
        });
    tCol.setVisible(false);
    taskTable.getColumns().add(tCol);
    // END Status

    // BEGIN Component id (hidden)
    tCol = new TableColumn<>();
    tCol.setText("Component Id");
    tCol.setCellValueFactory(
        (value) -> {
          return new SimpleStringProperty(value.getValue().getComponentId());
        });
    tCol.setVisible(false);
    taskTable.getColumns().add(tCol);
    // END Component id (hidden)

    // BEGIN Concept
    TableColumn<LocalTask, SimpleDisplayConcept> conceptCol = new TableColumn<>();
    conceptCol.setText("Concept");
    conceptCol.setCellValueFactory(
        (value) -> {
          if (value.getValue().getComponentId() == null) {
            LOG.error("Component ID for task {} is null", value.getValue().getId());

            return new SimpleObjectProperty<SimpleDisplayConcept>();
          }
          UUID componentUuid = null;
          try {
            componentUuid = UUID.fromString(value.getValue().getComponentId());
          } catch (IllegalArgumentException e) {
            LOG.error("Component ID for task {} is not a valid UUID", value.getValue().getId());

            return new SimpleObjectProperty<SimpleDisplayConcept>();
          }

          ConceptVersionBI containingConcept = null;
          ComponentChronicleBI componentChronicle = WBUtility.getComponentChronicle(componentUuid);
          if (componentChronicle == null) {
            LOG.warn(
                "Component ID for task "
                    + value.getValue().getId()
                    + " retrieved a null componentChronicle");

            containingConcept = WBUtility.getConceptVersion(componentUuid);
            if (containingConcept == null) {
              LOG.error(
                  "Component ID for task "
                      + value.getValue().getId()
                      + " retrieved a null concept");

              return new SimpleObjectProperty<SimpleDisplayConcept>();
            }
          } else {
            try {
              containingConcept =
                  componentChronicle
                      .getEnclosingConcept()
                      .getVersion(WBUtility.getViewCoordinate());
            } catch (Exception e) {
              LOG.error(
                  "Failed getting version from ComponentChronicleBI task "
                      + value.getValue().getId()
                      + ".  Caught "
                      + e.getClass().getName()
                      + " "
                      + e.getLocalizedMessage());
              e.printStackTrace();
            }
            if (containingConcept == null) {
              LOG.error(
                  "ComponentChronicleBI task "
                      + value.getValue().getId()
                      + " contained a null enclosing concept");

              return new SimpleObjectProperty<SimpleDisplayConcept>();
            }
          }

          if (componentChronicle == null) {
            LOG.warn(
                "Component id "
                    + componentUuid
                    + " for task "
                    + value.getValue().getId()
                    + " is a concept, not just a component.");
          }
          SimpleDisplayConcept displayConcept = new SimpleDisplayConcept(containingConcept);
          return new SimpleObjectProperty<SimpleDisplayConcept>(displayConcept);
        });
    taskTable.getColumns().add(conceptCol);
    // END concept

    // BEGIN Concept
    TableColumn<LocalTask, String> conceptIdCol = new TableColumn<>();
    conceptIdCol.setText("Concept Id");
    conceptIdCol.setCellValueFactory(
        (value) -> {
          if (value.getValue().getComponentId() == null) {
            LOG.error("Component ID for task {} is null", value.getValue().getId());

            return new SimpleStringProperty();
          }
          UUID componentUuid = null;
          try {
            componentUuid = UUID.fromString(value.getValue().getComponentId());
          } catch (IllegalArgumentException e) {
            LOG.error("Component ID for task {} is not a valid UUID", value.getValue().getId());

            return new SimpleStringProperty();
          }

          ConceptVersionBI containingConcept = null;
          ComponentChronicleBI componentChronicle = WBUtility.getComponentChronicle(componentUuid);
          if (componentChronicle == null) {
            LOG.warn(
                "Component ID for task "
                    + value.getValue().getId()
                    + " retrieved a null componentChronicle");

            containingConcept = WBUtility.getConceptVersion(componentUuid);
            if (containingConcept == null) {
              LOG.error(
                  "Component ID for task "
                      + value.getValue().getId()
                      + " retrieved a null concept");

              return new SimpleStringProperty();
            }
          } else {
            try {
              containingConcept =
                  componentChronicle
                      .getEnclosingConcept()
                      .getVersion(WBUtility.getViewCoordinate());
            } catch (Exception e) {
              LOG.error(
                  "Failed getting version from ComponentChronicleBI task "
                      + value.getValue().getId()
                      + ".  Caught "
                      + e.getClass().getName()
                      + " "
                      + e.getLocalizedMessage());
              e.printStackTrace();
            }

            if (containingConcept == null) {
              LOG.error(
                  "ComponentChronicleBI task "
                      + value.getValue().getId()
                      + " contained a null enclosing concept");

              return new SimpleStringProperty();
            }
          }

          if (componentChronicle == null) {
            LOG.warn(
                "Component id "
                    + componentUuid
                    + " for task "
                    + value.getValue().getId()
                    + " is a concept, not just a component.");
          }

          UUID uuid = containingConcept.getPrimordialUuid();
          return new SimpleStringProperty(uuid.toString());
        });
    conceptIdCol.setVisible(false);
    taskTable.getColumns().add(conceptIdCol);
    // END concept ID

    float colWidth = 1.0f / taskTable.getColumns().size();
    for (TableColumn<LocalTask, ?> col : taskTable.getColumns()) {
      col.prefWidthProperty().bind(taskTable.widthProperty().multiply(colWidth).subtract(3.0));
      col.setCellFactory(new MyCellFactoryCallback<>());
    }

    claimTasksButton.setOnAction(
        (action) -> {
          claimTasksButton.setDisable(true);
          final BusyPopover claimPopover =
              BusyPopover.createBusyPopover("Claiming new tasks...", claimTasksButton);

          Utility.execute(
              () -> {
                try {
                  wfEngine_.claim(10, user);
                  Platform.runLater(
                      () -> {
                        claimPopover.hide();
                        claimTasksButton.setDisable(false);
                        refreshContent();
                      });
                } catch (Exception e) {
                  logger.error("Unexpected error claiming tasks", e);
                }
              });
        });

    synchronizeButton.setOnAction(
        (action) -> {
          synchronizeButton.setDisable(true);
          final BusyPopover synchronizePopover =
              BusyPopover.createBusyPopover("Synchronizing tasks...", synchronizeButton);

          Utility.execute(
              () -> {
                try {
                  wfEngine_.synchronizeWithRemote();
                  Platform.runLater(
                      () -> {
                        synchronizePopover.hide();
                        synchronizeButton.setDisable(false);
                        refreshContent();
                      });
                } catch (Exception e) {
                  logger.error("Unexpected error synchronizing tasks", e);
                }
              });
        });
  }