<commit_before>/*
 * Copyright 2002-2013 SCOOP Software GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.scoopgmbh.copper.monitoring.client.ui.workflowclasssesctree;

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

import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.util.Callback;
import javafx.util.StringConverter;

import com.google.common.base.Optional;

import de.scoopgmbh.copper.monitoring.client.form.issuereporting.IssueReporter;
import de.scoopgmbh.copper.monitoring.client.util.WorkflowVersion;

public class WorkflowClassesTreeController {
	private final TreeView<DisplayWorkflowClassesModel> treeView;
	
	public WorkflowClassesTreeController(final TreeView<DisplayWorkflowClassesModel> treeView, IssueReporter issueReporter) {
		super();
		this.treeView = treeView;
		
		treeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
		treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<DisplayWorkflowClassesModel>>() {
			@Override
			public void changed(ObservableValue<? extends TreeItem<DisplayWorkflowClassesModel>> observable,
					TreeItem<DisplayWorkflowClassesModel> oldValue, TreeItem<DisplayWorkflowClassesModel> newValue) {
				
				if (newValue!=null && newValue.getValue()!=null /*&& newValue.getChildren().isEmpty()*/){
					WorkflowVersion workflowClassesModel = newValue.getValue().value;
					selectedItem.set(workflowClassesModel);
					expand(newValue);
				}
				
			}
		});
		
		final ContextMenu contextMenu = new ContextMenu();
		final MenuItem copy = new MenuItem("copy");
		copy.setAccelerator(new KeyCodeCombination(KeyCode.C, KeyCombination.SHORTCUT_DOWN));
		copy.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				final Clipboard clipboard = Clipboard.getSystemClipboard();
			    final ClipboardContent content = new ClipboardContent();
			    content.putString(treeView.getSelectionModel().getSelectedItem().getValue().displayname);
			    clipboard.setContent(content);
			}
		});
		copy.disableProperty().bind(treeView.getSelectionModel().selectedItemProperty().isNull());
		contextMenu.getItems().add(copy);
		treeView.setContextMenu(contextMenu);
	}
	
	private void expand(TreeItem<DisplayWorkflowClassesModel> newValue){
		for (TreeItem<DisplayWorkflowClassesModel> item: newValue.getChildren()){
			expand(item);
		}
		newValue.setExpanded(true);
	}
	
	public static class DisplayWorkflowClassesModel{
		public WorkflowVersion value;
		public String displayname;
		public DisplayWorkflowClassesModel(WorkflowVersion value, String displayname) {
			super();
			this.value = value;
			this.displayname = displayname;
		}
	}
	
	
	private Optional<TreeItem<DisplayWorkflowClassesModel>> findMajorItem(WorkflowVersion newWorkflowVersion,List<TreeItem<DisplayWorkflowClassesModel>> result){
		for (TreeItem<DisplayWorkflowClassesModel> classnameItem: result){
			if (newWorkflowVersion.alias.getValue()!=null && newWorkflowVersion.alias.getValue().equals(classnameItem.getValue().value.alias.getValue())){
				for (TreeItem<DisplayWorkflowClassesModel> majorItem: classnameItem.getChildren()){
					if (newWorkflowVersion.versionMajor.getValue().equals(majorItem.getValue().value.versionMajor.getValue())){
						return Optional.of(majorItem);
					}
				}
			}
		}
		return Optional.absent();
	}
	
	private Optional<TreeItem<DisplayWorkflowClassesModel>> findMinorVersion(Long versionMinor, TreeItem<DisplayWorkflowClassesModel> majorItem){
		for (TreeItem<DisplayWorkflowClassesModel> item : majorItem.getChildren()){
			if (versionMinor!=null && versionMinor.equals(item.getValue().value.versionMinor.getValue())){
				return Optional.of(item);
			}
		}
		return Optional.absent();
	}
	
	
	public String getMajorVersionText(WorkflowVersion workflowVersion){
		return "major: "+ nullFix(workflowVersion.versionMajor.getValue());
	}
	
	public String getMinorVersionText(WorkflowVersion workflowVersion){
		return "minor: "+nullFix(workflowVersion.versionMinor.getValue());
	}
	
	public String getPatchVersionText(WorkflowVersion workflowVersion){
		return  nullFix(workflowVersion.versionMajor.get())+"."+
				nullFix(workflowVersion.versionMinor.get())+"."+
				nullFix(workflowVersion.patchlevel.get())+ ": "+
				"class: "+nullFix(workflowVersion.classname.get());
	}
	
	public String nullFix(Object object){
		return object==null?"?": object.toString();
	}
	
	public List<TreeItem<DisplayWorkflowClassesModel>> groupToTreeItem(List<WorkflowVersion> list){
		//from flat List: alias , majorversion, minorversion
		//totree: 
		//alias 
		//	->majorversion
		//		->minorversion		
		//			->patchlevel + classname	
		
		List<TreeItem<DisplayWorkflowClassesModel>> result = new ArrayList<TreeItem<DisplayWorkflowClassesModel>>();
		for (WorkflowVersion newWorkflowVersion: list){
			Optional<TreeItem<DisplayWorkflowClassesModel>> existingMajorItem=findMajorItem(newWorkflowVersion,result);
			
			TreeItem<DisplayWorkflowClassesModel> majorVersionItemToAdd;
			if (existingMajorItem.isPresent()){
				majorVersionItemToAdd = existingMajorItem.get();
			} else {
				TreeItem<DisplayWorkflowClassesModel> classnameItemToAdd;
				classnameItemToAdd = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, nullFix(newWorkflowVersion.alias.get())));
				result.add(classnameItemToAdd);
				majorVersionItemToAdd = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getMajorVersionText(newWorkflowVersion)));
				classnameItemToAdd.getChildren().add(majorVersionItemToAdd);
			}
			
			Optional<TreeItem<DisplayWorkflowClassesModel>> exintingMinorItem = findMinorVersion(newWorkflowVersion.versionMinor.get(),majorVersionItemToAdd);
			TreeItem<DisplayWorkflowClassesModel> minorItem = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getMinorVersionText(newWorkflowVersion) ));
			if (exintingMinorItem.isPresent()){
				minorItem=exintingMinorItem.get();
			} else {
				majorVersionItemToAdd.getChildren().add(minorItem);
			}
			minorItem.getChildren().add(new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getPatchVersionText(newWorkflowVersion) )));

			
		}
		
		return result;
	}

	public void refresh(List<WorkflowVersion> newItems) {
        treeView.setShowRoot(false);
		TreeItem<DisplayWorkflowClassesModel> rootItem = new TreeItem<DisplayWorkflowClassesModel>();
		rootItem.getChildren().addAll(groupToTreeItem(newItems));
		treeView.setRoot(rootItem);

		treeView.setCellFactory(new Callback<TreeView<DisplayWorkflowClassesModel>, TreeCell<DisplayWorkflowClassesModel>>() {
		    @Override
		    public TreeCell<DisplayWorkflowClassesModel> call(TreeView<DisplayWorkflowClassesModel> listView) {
		        return new TextFieldTreeCell<DisplayWorkflowClassesModel>(new StringConverter<DisplayWorkflowClassesModel>() {
					@Override<commit_msg>Fix for missing workflow alias<commit_after>/*
 * Copyright 2002-2013 SCOOP Software GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.scoopgmbh.copper.monitoring.client.ui.workflowclasssesctree;

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

import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.util.Callback;
import javafx.util.StringConverter;

import com.google.common.base.Optional;

import de.scoopgmbh.copper.monitoring.client.form.issuereporting.IssueReporter;
import de.scoopgmbh.copper.monitoring.client.util.WorkflowVersion;

public class WorkflowClassesTreeController {
	private final TreeView<DisplayWorkflowClassesModel> treeView;
	
	public WorkflowClassesTreeController(final TreeView<DisplayWorkflowClassesModel> treeView, IssueReporter issueReporter) {
		super();
		this.treeView = treeView;
		
		treeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
		treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<DisplayWorkflowClassesModel>>() {
			@Override
			public void changed(ObservableValue<? extends TreeItem<DisplayWorkflowClassesModel>> observable,
					TreeItem<DisplayWorkflowClassesModel> oldValue, TreeItem<DisplayWorkflowClassesModel> newValue) {
				
				if (newValue!=null && newValue.getValue()!=null /*&& newValue.getChildren().isEmpty()*/){
					WorkflowVersion workflowClassesModel = newValue.getValue().value;
					selectedItem.set(workflowClassesModel);
					expand(newValue);
				}
				
			}
		});
		
		final ContextMenu contextMenu = new ContextMenu();
		final MenuItem copy = new MenuItem("copy");
		copy.setAccelerator(new KeyCodeCombination(KeyCode.C, KeyCombination.SHORTCUT_DOWN));
		copy.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				final Clipboard clipboard = Clipboard.getSystemClipboard();
			    final ClipboardContent content = new ClipboardContent();
			    content.putString(treeView.getSelectionModel().getSelectedItem().getValue().displayname);
			    clipboard.setContent(content);
			}
		});
		copy.disableProperty().bind(treeView.getSelectionModel().selectedItemProperty().isNull());
		contextMenu.getItems().add(copy);
		treeView.setContextMenu(contextMenu);
	}
	
	private void expand(TreeItem<DisplayWorkflowClassesModel> newValue){
		for (TreeItem<DisplayWorkflowClassesModel> item: newValue.getChildren()){
			expand(item);
		}
		newValue.setExpanded(true);
	}
	
	public static class DisplayWorkflowClassesModel{
		public WorkflowVersion value;
		public String displayname;
		public DisplayWorkflowClassesModel(WorkflowVersion value, String displayname) {
			super();
			this.value = value;
			this.displayname = displayname;
		}
	}
	
	
	private Optional<TreeItem<DisplayWorkflowClassesModel>> findMajorItem(WorkflowVersion newWorkflowVersion,List<TreeItem<DisplayWorkflowClassesModel>> result){
		for (TreeItem<DisplayWorkflowClassesModel> classnameItem: result){
			if (newWorkflowVersion.alias.getValue()!=null && newWorkflowVersion.alias.getValue().equals(classnameItem.getValue().value.alias.getValue())){
				for (TreeItem<DisplayWorkflowClassesModel> majorItem: classnameItem.getChildren()){
					if (newWorkflowVersion.versionMajor.getValue().equals(majorItem.getValue().value.versionMajor.getValue())){
						return Optional.of(majorItem);
					}
				}
			}
		}
		return Optional.absent();
	}
	
	private Optional<TreeItem<DisplayWorkflowClassesModel>> findMinorVersion(Long versionMinor, TreeItem<DisplayWorkflowClassesModel> majorItem){
		for (TreeItem<DisplayWorkflowClassesModel> item : majorItem.getChildren()){
			if (versionMinor!=null && versionMinor.equals(item.getValue().value.versionMinor.getValue())){
				return Optional.of(item);
			}
		}
		return Optional.absent();
	}
	
	
	public String getMajorVersionText(WorkflowVersion workflowVersion){
		return "major: "+ nullFix(workflowVersion.versionMajor.getValue());
	}
	
	public String getMinorVersionText(WorkflowVersion workflowVersion){
		return "minor: "+nullFix(workflowVersion.versionMinor.getValue());
	}
	
	public String getPatchVersionText(WorkflowVersion workflowVersion){
		return  nullFix(workflowVersion.versionMajor.get())+"."+
				nullFix(workflowVersion.versionMinor.get())+"."+
				nullFix(workflowVersion.patchlevel.get())+ ": "+
				"class: "+nullFix(workflowVersion.classname.get());
	}
	
	public String nullFix(Object object){
		return object==null ? "?" : object.toString();
	}
	
	private String getAlias(WorkflowVersion workflowVersion) {
		String alias = workflowVersion.alias.get();
		if(alias == null) {
			alias = workflowVersion.classname.get();
			if(alias == null) {
				alias = "?";
			} else {
				alias = alias.substring(alias.lastIndexOf('.') + 1);
			}
		}
		return alias;
	}

	public List<TreeItem<DisplayWorkflowClassesModel>> groupToTreeItem(List<WorkflowVersion> list){
		//from flat List: alias , majorversion, minorversion
		//totree: 
		//alias 
		//	->majorversion
		//		->minorversion		
		//			->patchlevel + classname	
		
		List<TreeItem<DisplayWorkflowClassesModel>> result = new ArrayList<TreeItem<DisplayWorkflowClassesModel>>();
		for (WorkflowVersion newWorkflowVersion: list){
			Optional<TreeItem<DisplayWorkflowClassesModel>> existingMajorItem=findMajorItem(newWorkflowVersion,result);
			
			TreeItem<DisplayWorkflowClassesModel> majorVersionItemToAdd;
			if (existingMajorItem.isPresent()){
				majorVersionItemToAdd = existingMajorItem.get();
			} else {
				TreeItem<DisplayWorkflowClassesModel> classnameItemToAdd;
				classnameItemToAdd = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getAlias(newWorkflowVersion)));
				result.add(classnameItemToAdd);
				majorVersionItemToAdd = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getMajorVersionText(newWorkflowVersion)));
				classnameItemToAdd.getChildren().add(majorVersionItemToAdd);
			}
			
			Optional<TreeItem<DisplayWorkflowClassesModel>> exintingMinorItem = findMinorVersion(newWorkflowVersion.versionMinor.get(),majorVersionItemToAdd);
			TreeItem<DisplayWorkflowClassesModel> minorItem = new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getMinorVersionText(newWorkflowVersion) ));
			if (exintingMinorItem.isPresent()){
				minorItem=exintingMinorItem.get();
			} else {
				majorVersionItemToAdd.getChildren().add(minorItem);
			}
			minorItem.getChildren().add(new TreeItem<DisplayWorkflowClassesModel>(new DisplayWorkflowClassesModel(newWorkflowVersion, getPatchVersionText(newWorkflowVersion) )));

			
		}
		
		return result;
	}

	public void refresh(List<WorkflowVersion> newItems) {
        treeView.setShowRoot(false);
		TreeItem<DisplayWorkflowClassesModel> rootItem = new TreeItem<DisplayWorkflowClassesModel>();
		rootItem.getChildren().addAll(groupToTreeItem(newItems));
		treeView.setRoot(rootItem);

		treeView.setCellFactory(new Callback<TreeView<DisplayWorkflowClassesModel>, TreeCell<DisplayWorkflowClassesModel>>() {
		    @Override
		    public TreeCell<DisplayWorkflowClassesModel> call(TreeView<DisplayWorkflowClassesModel> listView) {
		        return new TextFieldTreeCell<DisplayWorkflowClassesModel>(new StringConverter<DisplayWorkflowClassesModel>() {
					@Override
{'fraction_non_alphanumeric': 0.1036574379917122, 'fraction_numerical': 0.0015014113266470482, 'mean_word_length': 6.104095563139932, 'pattern_counts': {'":': 3, '<': 101, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2504388', 'n_tokens_mistral': 5255, 'n_tokens_neox': 4663, 'n_words': 819}