package com.celements.navigation.service;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xwiki.bridge.event.DocumentUpdatedEvent;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.Requirement;
import org.xwiki.context.Execution;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.observation.EventListener;
import org.xwiki.observation.event.Event;

import com.celements.common.classes.IClassCollectionRole;
import com.celements.navigation.NavigationClasses;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;

@Component("TreeNodeDocumentUpdatedListener")
public class TreeNodeDocumentUpdatedListener implements EventListener {

  private static Log LOGGER = LogFactory.getFactory().getInstance(
      TreeNodeDocumentUpdatedListener.class);

  @Requirement
  ITreeNodeCache treeNodeCache;

  @Requirement("celements.celNavigationClasses")
  IClassCollectionRole navClasses;

  @Requirement
  Execution execution;

  private XWikiContext getContext() {
    return (XWikiContext)execution.getContext().getProperty("xwikicontext");
  }

  private NavigationClasses getNavClasses() {
    return (NavigationClasses) navClasses;
  }

  public String getName() {
    return "TreeNodeDocumentUpdatedListener";
  }

  public List<Event> getEvents() {
    return Arrays.asList((Event)new DocumentUpdatedEvent());
  }

  public void onEvent(Event event, Object source, Object data) {
    XWikiDocument document = (XWikiDocument) source;
    XWikiDocument origDoc = getOrginialDocument(source);
    if ((document != null) && (origDoc != null)) {
      LOGGER.debug("onEvent: got event for [" + event.getClass() + "] on document ["
          + document.getDocumentReference() + "].");
      if (checkMenuItemDiffs(document, origDoc)) {
        treeNodeCache.flushMenuItemCache();
      }
    } else {
      LOGGER.trace("onEvent: got event for [" + event.getClass() + "] on source ["
          + source + "] and data [" + data + "] -> skip.");
    }
  }

  boolean checkMenuItemDiffs(XWikiDocument document, XWikiDocument origDoc) {
    BaseObject menuItemObj = document.getXObject(getNavClasses().getMenuItemClassRef(
        getContext().getDatabase()));
    BaseObject menuItemOrigObj = origDoc.getXObject(getNavClasses().getMenuItemClassRef(
        getContext().getDatabase()));
    if ((menuItemObj != null) && (menuItemOrigObj != null)) {
      int newPos = menuItemObj.getIntValue(NavigationClasses.MENU_POSITION_FIELD, -1);
      int oldPos = menuItemOrigObj.getIntValue(NavigationClasses.MENU_POSITION_FIELD, -1);
      if (newPos != oldPos) {
        return true;
      } else {
        DocumentReference parentRef = document.getParentReference();
        DocumentReference parentOrigRef = origDoc.getParentReference();
        if ((parentRef != null) && (parentOrigRef != null)) {
          return !parentRef.equals(parentOrigRef);
        } else {
          return ((parentRef != null) || (parentOrigRef != null));
        }
      }
    } else if ((menuItemObj != null) || (menuItemOrigObj != null)) {
      return true;
    }
    return false;
  }

  private XWikiDocument getOrginialDocument(Object source) {
    if (source != null) {
      return ((XWikiDocument) source).getOriginalDocument();
    }
    return null;
  }

}

@@ -1366,24 +1366,85 @@
 getName() %7B%0A
+    LOGGER.trace(%22TreeNodeDocumentUpdatedListener getName%22);%0A
     return %22
@@ -1513,24 +1513,87 @@
 tEvents() %7B%0A
+    LOGGER.trace(%22TreeNodeDocumentUpdatedListener getEvents%22);%0A
     return A
@@ -1707,24 +1707,93 @@
 ect data) %7B%0A
+    LOGGER.trace(%22TreeNodeDocumentUpdatedListener onEvent: start.%22);%0A
     XWikiDoc
@@ -1961,16 +1961,48 @@
 .debug(%22
+TreeNodeDocumentUpdatedListener 
 onEvent:
@@ -2010,32 +2010,42 @@
 got event for %5B%22
+%0A         
  + event.getClas
@@ -2067,26 +2067,16 @@
 ument %5B%22
-%0A         
  + docum
@@ -2101,16 +2101,26 @@
 erence()
+%0A         
  + %22%5D.%22)
@@ -2168,24 +2168,104 @@
 origDoc)) %7B%0A
+        LOGGER.trace(%22TreeNodeDocumentUpdatedListener flush menu item cache.%22);%0A
         tree
@@ -2796,24 +2796,181 @@
 tabase()));%0A
+    LOGGER.trace(%22TreeNodeDocumentUpdatedListener checkMenuItemDiffs menuItemObj %5B%22%0A        + menuItemObj + %22%5D, menuItemOrigObj %5B%22 + menuItemOrigObj + %22%5D%22);%0A
     if ((men

add logging to TreeNodeDocumentUpdatedListener