/*******************************************************************************
 * Copyright (c) 2010 Boeing.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Boeing - initial API and implementation
 *******************************************************************************/
package org.eclipse.ote.ui.message.watch;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IRegistryEventListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.ui.swt.Displays;
import org.eclipse.osee.framework.ui.swt.ImageManager;
import org.eclipse.osee.ote.message.Message;
import org.eclipse.osee.ote.message.data.MessageData;
import org.eclipse.osee.ote.message.elements.ArrayElement;
import org.eclipse.osee.ote.message.elements.Element;
import org.eclipse.ote.ui.message.internal.WatchImages;
import org.eclipse.ote.ui.message.tree.AbstractTreeNode;
import org.eclipse.ote.ui.message.tree.ElementNode;
import org.eclipse.ote.ui.message.tree.INodeVisitor;
import org.eclipse.ote.ui.message.tree.MessageNode;
import org.eclipse.ote.ui.message.tree.RootNode;
import org.eclipse.ote.ui.message.tree.WatchedElementNode;
import org.eclipse.ote.ui.message.tree.WatchedMessageNode;
import org.eclipse.ote.ui.message.view.MessageInfoComposite;
import org.eclipse.ote.ui.message.view.MessageInfoSelectionListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.osgi.framework.Bundle;

/**
 * @author Ken J. Aguilar
 */
public class DetailsBox implements IRegistryEventListener {
   private static final String EXTENSION_POINT_ID = "org.eclipse.ote.ui.message.detailsProvider";
   private static final String ELEMENT = "TabProvider";
   private static final String PAYLOAD_TXT = "\npayload:\n    0:  ";
   private static final String HEADER_TXT = "header:\n    0:  ";
   private static final int HEX_DUMP_BYTES_PER_ROW = 16;
   private static final int HEX_DUMP_CHARS_PER_BYTE = 3;

   /**
    * number of characters that lead each row in the hex dump, these characters represent the byte offset indicator for
    * each hex row
    */
   private static int HEX_DUMP_PREFIX_CHARS = 8;
   private static int HEX_DUMP_NON_PREFIX_CHAR = HEX_DUMP_BYTES_PER_ROW * HEX_DUMP_CHARS_PER_BYTE;
   /**
    * total number of characters per hex dump row including the newline character
    */
   private static int HEX_DUMP_LINE_WIDTH = HEX_DUMP_PREFIX_CHARS + HEX_DUMP_NON_PREFIX_CHAR + 1;

   private final TabFolder infoFolder;
   private final TabItem hexDumpTab;
   private final TabItem databaseTab;
   private final StyledText hexDumpTxt;
   private final Font courier;
   private final Image hexImg;
   private final MessageInfoComposite databaseComposite;
   private final StringBuilder strBuilder = new StringBuilder(1024*128);
   private TabItem selectedTab;
   private final HashMap<String, TabItem> detailsProviderMap = new HashMap<String, TabItem>();
   private AbstractTreeNode lastDatabaseNode;

   private static final String[] hexTbl = new String[256];

   static {
      for (int i = 0; i < 256; i++) {
         hexTbl[i] = String.format("%02X ", i);
      }
   }

   public DetailsBox(Composite parent) {
      hexImg = ImageManager.getImage(WatchImages.HEX);
      courier = new Font(parent.getDisplay(), "Courier", 10, SWT.NORMAL);
      /* Create Text box to display values of selected messages */
      infoFolder = new TabFolder(parent, SWT.BORDER);

      hexDumpTab = new TabItem(infoFolder, SWT.NONE);
      hexDumpTab.setText("Hex Dump");
      hexDumpTab.setImage(hexImg);
      hexDumpTab.setToolTipText("displays hex dump of currently selected message");
      hexDumpTxt = new StyledText(infoFolder, SWT.DOUBLE_BUFFERED | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
      hexDumpTxt.setFont(courier);
      hexDumpTab.setControl(hexDumpTxt);

      databaseTab = new TabItem(infoFolder, SWT.NONE);
      databaseTab.setText("Database Info");
      databaseTab.setToolTipText("Displays static info about a selected message");
      databaseComposite = new MessageInfoComposite(infoFolder);
      databaseTab.setControl(databaseComposite);
      lastDatabaseNode = null;

      installExtensionRegistryListener();

      infoFolder.addSelectionListener(new SelectionAdapter() {

         @Override
         public void widgetSelected(SelectionEvent e) {
            selectedTab = (TabItem) e.item;
         }
      });
      selectedTab = infoFolder.getItem(infoFolder.getSelectionIndex());
   }

   /**
    * display details about specified node
    * 
    * @param node node whose details will be displayed in the detail window of the GUI
    */
   public void setDetailText(final AbstractTreeNode node) {
      if (selectedTab == null) {
         return;
      }
      if (selectedTab == hexDumpTab) {
         renderHex(node);
      }
      else if (selectedTab == databaseTab) {
         updateDatabaseInfo(node);
      } else {
         DetailsProvider provider = (DetailsProvider) selectedTab.getControl();
         provider.render(node);
      }

   }

   public void dispose() {
      IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
      if (extensionRegistry != null) {
         extensionRegistry.removeListener(this);
      }

      if(!courier.isDisposed()){
         courier.dispose();
      }
   }

   public void selectNode(AbstractTreeNode node) {
      if (node instanceof WatchedElementNode) {
         WatchedElementNode elementNode = (WatchedElementNode) node;
         WatchedMessageNode msgNode = (WatchedMessageNode) elementNode.getMessageNode();
         int offset = elementNode.getElement().getByteOffset() + elementNode.getElement().getMsb() / 8;
         hexDumpTxt.setTopIndex(msgNode.getSubscription().getMessage().getHeaderSize() / HEX_DUMP_BYTES_PER_ROW + offset / HEX_DUMP_BYTES_PER_ROW + 2);
      }
      setDetailText(node);
   }
   private void renderHex(AbstractTreeNode node) {
      if (!node.isEnabled()) {
         hexDumpTxt.setText(node.getName() + "\nDISABLED: " + node.getDisabledReason());
         return;
      }
      Point selection = hexDumpTxt.getSelection();
      int horizontalPixel = hexDumpTxt.getHorizontalPixel();
      int verticalPixel = hexDumpTxt.getTopPixel();
      int caret = hexDumpTxt.getCaretOffset();
      hexDumpTxt.setRedraw(false);
      final INodeVisitor<Object> visitor = new INodeVisitor<Object>() {
         @Override
         public Object elementNode(final ElementNode node) {
            hexDumpTxt.setStyleRange(null);
            WatchedMessageNode msgNode = (WatchedMessageNode) node.getMessageNode();
            if (!msgNode.getSubscription().isResolved()) {
               hexDumpTxt.setText(node.getName() + " not found in library");
               return null;
            }
            final Message<?, ?, ?> msg = msgNode.getSubscription().getMessage();
            if (msg.isDestroyed()) {
               return null;
            }

            int payloadStart = printByteDump(msg);
            Element e = ((WatchedElementNode) node).getElement();
            if (e != null) {
               if (!e.isNonMappingElement()) {
                  MessageData data = msg.getActiveDataSource();
                  int headerSize = data.getMsgHeader() == null ? 0 : data.getMsgHeader().getHeaderSize();
                  if (e.getByteOffset() >= data.getCurrentLength() - headerSize) {
                     hexDumpTxt.setText("element outside of current message size");
                     return null;
                  }
                  StyleRange range = new StyleRange();
                  range.background = Displays.getSystemColor(SWT.COLOR_GRAY);
                  range.foreground = Displays.getSystemColor(SWT.COLOR_BLACK);
                  int offset = e.getByteOffset() + e.getMsb() / 8;
                  range.length = (e.getLsb() - e.getMsb() + 8) / 8 * HEX_DUMP_CHARS_PER_BYTE - 1;

                  int line = offset / HEX_DUMP_BYTES_PER_ROW * HEX_DUMP_LINE_WIDTH;
                  int lineIndent = offset % HEX_DUMP_BYTES_PER_ROW * HEX_DUMP_CHARS_PER_BYTE;
                  range.start = line + lineIndent + payloadStart;

                  if(!(e instanceof ArrayElement)){

                     if (HEX_DUMP_PREFIX_CHARS + lineIndent + range.length >= HEX_DUMP_LINE_WIDTH) {
                        int remaining = range.length - (HEX_DUMP_LINE_WIDTH - lineIndent - 9);
                        int numberOfRanges =remaining / HEX_DUMP_NON_PREFIX_CHAR + 2;
                        StyleRange[] existing = hexDumpTxt.getStyleRanges();
                        final StyleRange[] ranges;
                        
                        if (existing.length != numberOfRanges) {
                        	ranges = new StyleRange[numberOfRanges];                        	
                        } else {
                        	ranges = existing;
                        }
                        
                        ranges[0] = range;
                        range.length -= remaining;
                        int c = 1;
                        while (remaining > 0) {
                        	StyleRange newRange = ranges[c];
                        	if (newRange == null) {
                        		newRange = new StyleRange();
                        		ranges[c] = newRange;                        		
                        	}
                           newRange.background = range.background;
                           newRange.foreground = range.foreground;
                           newRange.start = line + c * HEX_DUMP_LINE_WIDTH + payloadStart;
                           newRange.length = remaining < HEX_DUMP_NON_PREFIX_CHAR ? remaining : HEX_DUMP_NON_PREFIX_CHAR;
                           remaining -= newRange.length;
                           c++;
                        }
                        try{
                           hexDumpTxt.setStyleRanges(ranges);
                        } catch (Throwable th){
                           th.printStackTrace();
                        }
                     } else {
                        try{
                           hexDumpTxt.setStyleRange(range);
                        } catch (Throwable th){
                           th.printStackTrace();
                        }
                     }
                  }
               }
            }

            return node;
         }

         @Override
         public Object messageNode(final MessageNode node) {
            WatchedMessageNode msgNode = (WatchedMessageNode) node;
            final Message<?, ?, ?> msg = msgNode.getSubscription().getMessage();
            if (msg != null && !msg.isDestroyed()) {
               printByteDump(msg);
               hexDumpTxt.setStyleRange(null);
            }
            return node;
         }

         @Override
         public Object rootNode(RootNode node) {
            return node;
         }

      };
      node.visit(visitor);

      hexDumpTxt.setCaretOffset(caret);
      if (caret == selection.x) {
    	  selection.x = selection.y;
    	  selection.y = caret;
      }
      hexDumpTxt.setSelection(selection);
      hexDumpTxt.setTopPixel(verticalPixel);
      hexDumpTxt.setHorizontalPixel(horizontalPixel);
      hexDumpTxt.setRedraw(true);

   }

   private void updateDatabaseInfo(AbstractTreeNode node) {
      if (lastDatabaseNode == node) {
         return;
      }
      lastDatabaseNode = node;
      if (node == null) {
         databaseComposite.search("");
         return;
      }
      final INodeVisitor<Object> visitor = new INodeVisitor<Object>() {
         @Override
         public Object elementNode(final ElementNode node) {
            WatchedMessageNode msgNode = (WatchedMessageNode) node.getMessageNode();
            databaseComposite.search(msgNode.getMessageClassName());
            return node;
         }

         @Override
         public Object messageNode(final MessageNode node) {
            WatchedMessageNode msgNode = (WatchedMessageNode) node;
            databaseComposite.search(msgNode.getMessageClassName());
            return node;
         }

         @Override
         public Object rootNode(RootNode node) {
            return node;
         }
      };
      node.visit(visitor);
   }


   /**
    * writes message data to a buffer in hex format
    */
   private int printByteDump(Message<?, ?, ?> msg) {
      strBuilder.setLength(0);
      final byte[] data = msg.getData();
      int columnCount = 0;
      strBuilder.append(HEADER_TXT);
      for (int i = 0; i < msg.getHeaderSize(); i++) {
         if (columnCount == HEX_DUMP_BYTES_PER_ROW) {
            strBuilder.append('\n').append(String.format("%5d:  ", i));
            columnCount = 0;
         }
         strBuilder.append(hexTbl[data[i] & 0xFF]);
         columnCount++;
      }
      strBuilder.append(PAYLOAD_TXT);
      int payloadStart = strBuilder.length();
      columnCount = 0;
      for (int i = msg.getHeaderSize(); i < data.length; i++) {
         if (columnCount == HEX_DUMP_BYTES_PER_ROW) {
            strBuilder.append('\n').append(String.format("%5d:  ", i - msg.getHeaderSize()));
            columnCount = 0;
         }
         strBuilder.append(hexTbl[data[i] & 0xFF]);
         columnCount++;
      }
      strBuilder.append('\n');
      hexDumpTxt.setText(strBuilder.toString());
      return payloadStart;
   }

   private void installExtensionRegistryListener() {
      IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
      if (extensionRegistry == null) {
         throw new IllegalStateException("The extension registry is unavailable");
      }

      IExtensionPoint point = extensionRegistry.getExtensionPoint(EXTENSION_POINT_ID);
      if (point == null) {
         return;
      }
      added(point.getExtensions());
      extensionRegistry.addListener(this, EXTENSION_POINT_ID);
   }

   @Override
   public void added(IExtension[] extensions) {
      final List<IConfigurationElement> newElements = new LinkedList<IConfigurationElement>();
      for (IExtension extension : extensions) {
         for (IConfigurationElement element : extension.getConfigurationElements()) {
            if (element.getName().equals(ELEMENT)) {
               newElements.add(element);
            }
         }
      }
      Displays.ensureInDisplayThread(new Runnable() {
         @Override
         public void run() {
            for (IConfigurationElement element : newElements) {
               String className = element.getAttribute("className");
               String bundleName = element.getContributor().getName();
               Bundle bundle = Platform.getBundle(bundleName);
               if (bundle == null) {
                  OseeLog.logf(DetailsBox.class, Level.SEVERE,
                        "no bundle found for name %s while handling extension element %s", bundleName, element.getName());
                  return;
               }
               try {
                  Class<?> clazz = bundle.loadClass(className);
                  Class<? extends DetailsProvider> detailsClazz = clazz.asSubclass(DetailsProvider.class);
                  Constructor<? extends DetailsProvider> constructor =
                        detailsClazz.getConstructor(Composite.class, int.class);
                  try {
                     DetailsProvider provider = constructor.newInstance(infoFolder, SWT.NONE);
                     TabItem newTab = new TabItem(infoFolder, SWT.NONE);
                     newTab.setText(provider.getTabText());
                     newTab.setToolTipText(provider.getTabToolTipText());
                     newTab.setControl(provider);
                     detailsProviderMap.put(element.getDeclaringExtension().getUniqueIdentifier(), newTab);
                  } catch (Exception ex) {
                     OseeLog.logf(DetailsBox.class, Level.SEVERE, "failed to install details provider");
                  }
               } catch (ClassCastException ex) {
                  OseeLog.logf(
                        DetailsBox.class,
                        Level.SEVERE,
                        "the class named %s is not a subclass of %s", className,
                        DetailsProvider.class.getName());
               } catch (ClassNotFoundException ex) {
                  OseeLog.logf(DetailsBox.class, Level.SEVERE,
                        "no class found named %s in bundle %s", className, bundleName);
               } catch (NoSuchMethodException ex) {
                  OseeLog.logf(DetailsBox.class, Level.SEVERE,
                        "can't find appropriate constructor for %s", className);
               }
            }
         }
      });

   }

   @Override
   public void added(IExtensionPoint[] points) {

   }

   @Override
   public void removed(IExtension[] extensions) {
      final List<TabItem> removedElements = new LinkedList<TabItem>();
      for (IExtension extension : extensions) {
         TabItem item = detailsProviderMap.get(extension.getUniqueIdentifier());
         if (item != null) {
            removedElements.add(item);
         }
      }

      Displays.ensureInDisplayThread(new Runnable() {
         @Override
         public void run() {
            if (!infoFolder.isDisposed()){

               for (TabItem item : removedElements) {
                  if (selectedTab == item) {
                     selectedTab = null;
                     infoFolder.setSelection(hexDumpTab);
                  }
                  item.dispose();
               }
            }
         }
      });
   }

   @Override
   public void removed(IExtensionPoint[] arg0) {
   }

   public void setMessageInfoSelectionListener(MessageInfoSelectionListener listener) {
      databaseComposite.setSelectionListener(listener);
   }
}
