package ch.elexis.core.findings.ui.composites;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import ch.elexis.core.findings.ICoding;
import ch.elexis.core.findings.ICondition;
import ch.elexis.core.findings.ICondition.ConditionCategory;
import ch.elexis.core.findings.ICondition.ConditionStatus;
import ch.elexis.core.findings.ui.composites.CodingListComposite.CodingAdapter;
import ch.elexis.core.findings.ui.composites.NoteListComposite.NotesAdapter;
import ch.elexis.core.findings.ui.services.FindingsServiceComponent;
public class ConditionComposite extends Composite {
private ConditionCategory category;
private Optional<ICondition> condition;
private WritableValue transientConditionValue;
private ComboViewer statusViewer;
private TabFolder textOrCodingFolder;
private Text startTxt;
private Text endTxt;
private Text textTxt;
private CodingListComposite codingComposite;
private NoteListComposite notesComposite;
public ConditionComposite(ConditionCategory category, Composite parent, int style){
super(parent, style);
setLayout(new GridLayout(1, false));
this.category = category;
condition = Optional.empty();
statusViewer = new ComboViewer(this);
statusViewer.setContentProvider(new ArrayContentProvider());
statusViewer.setInput(ConditionStatus.values());
statusViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element){
if (element instanceof ConditionStatus) {
return ((ConditionStatus) element).getLocalized();
}
return super.getText(element);
}
});
startTxt = new Text(this, SWT.BORDER);
startTxt.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
startTxt.setMessage("Beginn Datum oder Beschreibung");
endTxt = new Text(this, SWT.BORDER);
endTxt.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
endTxt.setMessage("Ende Datum oder Beschreibung");
textOrCodingFolder = new TabFolder(this, SWT.NONE);
TabItem textItem = new TabItem(textOrCodingFolder, SWT.NONE, 0);
textItem.setText("Text");
textTxt = new Text(textOrCodingFolder, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);
textItem.setControl(textTxt);
TabItem codingItem = new TabItem(textOrCodingFolder, SWT.NONE, 1);
codingItem.setText("Kodierung");
codingComposite = new CodingListComposite(textOrCodingFolder, SWT.NONE);
codingComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
codingItem.setControl(codingComposite);
GridData folderGd = new GridData(GridData.FILL_HORIZONTAL);
folderGd.heightHint = 100;
textOrCodingFolder.setLayoutData(folderGd);
notesComposite = new NoteListComposite(this, SWT.NONE);
notesComposite.showTitle(true);
notesComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
initDataBinding();
}
private void initDataBinding(){
transientConditionValue = new WritableValue();
DataBindingContext bindingContext = new DataBindingContext();
IObservableValue targetObservable =
ViewersObservables.observeSingleSelection(statusViewer);
IObservableValue modelObservable = PojoObservables
.observeDetailValue(transientConditionValue, "status", TransientCondition.class);
bindingContext.bindValue(targetObservable, modelObservable);
targetObservable = SWTObservables.observeText(startTxt, SWT.Modify);
modelObservable = PojoObservables.observeDetailValue(transientConditionValue, "start",
TransientCondition.class);
bindingContext.bindValue(targetObservable, modelObservable);
targetObservable = SWTObservables.observeText(endTxt, SWT.Modify);
modelObservable = PojoObservables.observeDetailValue(transientConditionValue, "end",
TransientCondition.class);
bindingContext.bindValue(targetObservable, modelObservable);
targetObservable = SWTObservables.observeText(textTxt, SWT.Modify);
modelObservable =
PojoObservables.observeDetailValue(transientConditionValue, "text",
TransientCondition.class);
bindingContext.bindValue(targetObservable, modelObservable);
setCondition(null);
}
public Optional<ICondition> getCondition(){
return condition;
}
public void setCondition(final ICondition condition){
this.condition = Optional.ofNullable(condition);
if (this.condition.isPresent()) {
transientConditionValue
.setValue(TransientCondition.fromCondition(this.condition.get()));
// show coding if present
List<ICoding> coding = this.condition.get().getCoding();
if (coding != null && !coding.isEmpty()) {
textOrCodingFolder.setSelection(1);
}
} else {
TransientCondition emptyCondition = new TransientCondition();
emptyCondition.setStatus(ConditionStatus.ACTIVE);
emptyCondition.setDateRecorded(LocalDate.now());
transientConditionValue.setValue(emptyCondition);
}
// provide access adapter to notes composite
notesComposite.setInput(new NotesAdapter() {
@Override
public void removeNote(String note){
if (transientConditionValue.getValue() != null) {
((TransientCondition) transientConditionValue.getValue()).removeNote(note);
}
}
@Override
public List<String> getNotes(){
if (transientConditionValue.getValue() != null) {
return ((TransientCondition) transientConditionValue.getValue()).getNotes();
}
return Collections.emptyList();
}
@Override
public void addNote(String note){
if (transientConditionValue.getValue() != null) {
((TransientCondition) transientConditionValue.getValue()).addNote(note);
}
}
});
codingComposite.setInput(new CodingAdapter() {
@Override
public List<ICoding> getCoding(){
if (transientConditionValue.getValue() != null) {
return ((TransientCondition) transientConditionValue.getValue()).getCoding();
}
return Collections.emptyList();
}
@Override
public void setCoding(List<ICoding> coding){
if (transientConditionValue.getValue() != null) {
((TransientCondition) transientConditionValue.getValue()).setCoding(coding);
}
}
});
}
/**
* Creates a new ICondition if none set, and updates it with the actual values.
*/
public void udpateModel(){
if (!condition.isPresent()) {
condition = Optional
.of(FindingsServiceComponent.getService().getFindingsFactory().createCondition());
condition.get().setCategory(category);
}
if (transientConditionValue.getValue() instanceof TransientCondition) {
((TransientCondition) transientConditionValue.getValue()).toCondition(condition.get());
}
}
private static class TransientCondition {
private String text;
private List<ICoding> coding = new ArrayList<>();
private ConditionStatus status;
private LocalDate dateRecorded;
private List<String> notes = new ArrayList<>();
private String start;
private String end;
public List<ICoding> getCoding(){
return coding;
}
public void setCoding(List<ICoding> coding){
this.coding = coding;
}
public String getText(){
return text;
}
public void setText(String text){
this.text = text;
}
public ConditionStatus getStatus(){
return status;
}
public void setStatus(ConditionStatus status){
this.status = status;
}
public void setDateRecorded(LocalDate dateRecorded){
this.dateRecorded = dateRecorded;
}
public LocalDate getDateRecorded(){
return dateRecorded;
}
private void setNotes(List<String> notes){
this.notes = notes;
}
public List<String> getNotes(){
return notes;
}
public void addNote(String note){
notes.add(note);
}
public void removeNote(String note){
notes.remove(note);
}
public String getStart(){
return start;
}
public void setStart(String start){
this.start = start;
}
public String getEnd(){
return end;
}
public void setEnd(String end){
this.end = end;
}
public static TransientCondition fromCondition(ICondition condition){
TransientCondition ret = new TransientCondition();
ret.setStatus(condition.getStatus());
ret.setCoding(condition.getCoding());
condition.getDateRecorded().ifPresent(d -> ret.setDateRecorded(d));
condition.getText().ifPresent(t -> ret.setText(t));
ret.setNotes(new ArrayList<String>(condition.getNotes()));
condition.getStart().ifPresent(string -> ret.setStart(string));
condition.getEnd().ifPresent(string -> ret.setEnd(string));
return ret;
}
public void toCondition(ICondition condition){
condition.setStatus(getStatus());
condition.setCoding(getCoding());
if(dateRecorded != null) {
condition.setDateRecorded(getDateRecorded());
}
if(text != null) {
condition.setText(getText());
}
if (start != null) {
condition.setStart(start);
}
if (end != null) {
condition.setEnd(end);
}
if (notes != null) {
List<String> existingNotes = condition.getNotes();
for (String string : existingNotes) {
// remove no longer contained notes
if (!notes.contains(string)) {
condition.removeNote(string);
}
}
for (String string : notes) {
// add new notes
if (!existingNotes.contains(string)) {
condition.addNote(string);
}
}
}
}
}
}