/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.console;

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

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentAdapter;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IPositionUpdater;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineBackgroundEvent;
import org.eclipse.swt.custom.LineBackgroundListener;
import org.eclipse.swt.custom.LineStyleEvent;
import org.eclipse.swt.custom.LineStyleListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.internal.console.ConsoleDocumentAdapter;
import org.eclipse.ui.internal.console.ConsoleHyperlinkPosition;
import org.eclipse.ui.progress.WorkbenchJob;

/**
 * Default viewer used to display a <code>TextConsole</code>.
 * <p>
 * Clients may subclass this class.
 * </p>
 * 
 * @since 3.1
 */
public class TextConsoleViewer extends SourceViewer implements LineStyleListener, LineBackgroundListener, MouseTrackListener, MouseMoveListener, MouseListener {
    /**
     * Adapts document to the text widget.
     */
    private ConsoleDocumentAdapter documentAdapter;

    private IHyperlink hyperlink;

    private Cursor handCursor;

    private Cursor textCursor;

    private int consoleWidth = -1;

    private TextConsole console;

    private IPropertyChangeListener propertyChangeListener;

    private IDocumentListener documentListener = new IDocumentListener() {
        public void documentAboutToBeChanged(DocumentEvent event) {
        }

        public void documentChanged(DocumentEvent event) {
            updateLinks(event.fOffset);
        }
    };
    // event listener used to send event to hyperlink for IHyperlink2
    private Listener mouseUpListener = new Listener() {
		public void handleEvent(Event event) {
	        if (hyperlink != null) {
	            String selection = getTextWidget().getSelectionText();
	            if (selection.length() <= 0) {
	                if (event.button == 1) {
	                	if (hyperlink instanceof IHyperlink2) {
							((IHyperlink2) hyperlink).linkActivated(event);
						} else {
							hyperlink.linkActivated();
						}
	                }
	            }
	        }
		}
	};

    WorkbenchJob revealJob = new WorkbenchJob("Reveal End of Document") {//$NON-NLS-1$
        public IStatus runInUIThread(IProgressMonitor monitor) {
            StyledText textWidget = getTextWidget();
            if (textWidget != null && !textWidget.isDisposed()) {
                int lineCount = textWidget.getLineCount();
                textWidget.setTopIndex(lineCount - 1);
            }
            return Status.OK_STATUS;
        }
    };
    
    private IPositionUpdater positionUpdater = new IPositionUpdater() {
        public void update(DocumentEvent event) {
            try {
                IDocument document = getDocument();
                if (document != null) {
                    Position[] positions = document.getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
                    for (int i = 0; i < positions.length; i++) {
                        Position position = positions[i];
                        if (position.offset == event.fOffset && position.length<=event.fLength) {
                            position.delete();
                        }
                        if (position.isDeleted) {
                            document.removePosition(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY, position);
                        }
                    }
                }
            } catch (BadPositionCategoryException e) {
            }
        }
    };

    /**
     * Constructs a new viewer in the given parent for the specified console.
     * 
     * @param parent
     *            containing widget
     * @param console
     *            text console
     */
    public TextConsoleViewer(Composite parent, TextConsole console) {
        super(parent, null, SWT.V_SCROLL | SWT.H_SCROLL);
        this.console = console;

        IDocument document = console.getDocument();
        setDocument(document);

        StyledText styledText = getTextWidget();
        styledText.setDoubleClickEnabled(true);
        styledText.addLineStyleListener(this);
        styledText.addLineBackgroundListener(this);
        styledText.setEditable(true);
        setFont(console.getFont());
        styledText.addMouseTrackListener(this);
        styledText.addListener(SWT.MouseUp, mouseUpListener);

        ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
        propertyChangeListener = new HyperlinkColorChangeListener();
        colorRegistry.addListener(propertyChangeListener);

        revealJob.setSystem(true);
        document.addDocumentListener(documentListener);
        document.addPositionUpdater(positionUpdater);
    }

    /**
     * Sets the tab width used by this viewer.
     * 
     * @param tabWidth
     *            the tab width used by this viewer
     */
    public void setTabWidth(int tabWidth) {
        StyledText styledText = getTextWidget();
        int oldWidth = styledText.getTabs();
        if (tabWidth != oldWidth) {
            styledText.setTabs(tabWidth);
        }
    }

    /**
     * Sets the font used by this viewer.
     * 
     * @param font
     *            the font used by this viewer
     */
    public void setFont(Font font) {
        StyledText styledText = getTextWidget();
        Font oldFont = styledText.getFont();
        if (oldFont == font) {
            return;
        }
        if (font == null || !(font.equals(oldFont))) {
            styledText.setFont(font);
        }
    }

    /**
     * Positions the cursor at the end of the document.
     */
    protected void revealEndOfDocument() {
        revealJob.schedule(50);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.custom.LineStyleListener#lineGetStyle(org.eclipse.swt.custom.LineStyleEvent)
     */
    public void lineGetStyle(LineStyleEvent event) {
        IDocument document = getDocument();
        if (document != null && document.getLength() > 0) {
            ArrayList ranges = new ArrayList();
            int offset = event.lineOffset;
            int length = event.lineText.length();

            StyleRange[] partitionerStyles = ((IConsoleDocumentPartitioner) document.getDocumentPartitioner()).getStyleRanges(event.lineOffset, event.lineText.length());
            if (partitionerStyles != null) {
                for (int i = 0; i < partitionerStyles.length; i++) {
                    ranges.add(partitionerStyles[i]);
                }
            } else {
                ranges.add(new StyleRange(offset, length, null, null));
            }

            try {
                Position[] positions = getDocument().getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
                Position[] overlap = findPosition(offset, length, positions);
                Color color = JFaceColors.getHyperlinkText(Display.getCurrent());
                if (overlap != null) {
                    for (int i = 0; i < overlap.length; i++) {
                        Position position = overlap[i];
                        StyleRange linkRange = new StyleRange(position.offset, position.length, color, null);
                        linkRange.underline = true;
                        override(ranges, linkRange);
                    }
                }
            } catch (BadPositionCategoryException e) {
            }

            if (ranges.size() > 0) {
                event.styles = (StyleRange[]) ranges.toArray(new StyleRange[ranges.size()]);
            }
        }
    }

    private void override(List ranges, StyleRange newRange) {
        if (ranges.isEmpty()) {
            ranges.add(newRange);
            return;
        }

        int start = newRange.start;
        int end = start + newRange.length;
        for (int i = 0; i < ranges.size(); i++) {
            StyleRange existingRange = (StyleRange) ranges.get(i);
            int rEnd = existingRange.start + existingRange.length;
            if (end <= existingRange.start || start >= rEnd) {
                continue;
            }

            if (start < existingRange.start && end > existingRange.start) {
                start = existingRange.start;
            }

            if (start >= existingRange.start && end <= rEnd) {
                existingRange.length = start - existingRange.start;
                ranges.add(++i, newRange);
                if (end != rEnd) {
                    ranges.add(++i, new StyleRange(end, rEnd - end - 1, existingRange.foreground, existingRange.background));
                }
                return;
            } else if (start >= existingRange.start && start < rEnd) {
                existingRange.length = start - existingRange.start;
                ranges.add(++i, newRange);
            } else if (end >= rEnd) {
                ranges.remove(i);
            } else {
                ranges.add(++i, new StyleRange(end + 1, rEnd - end + 1, existingRange.foreground, existingRange.background));
            }
        }
    }

    /**
     * Binary search for the positions overlapping the given range
     * 
     * @param offset
     *            the offset of the range
     * @param length
     *            the length of the range
     * @param positions
     *            the positions to search
     * @return the positions overlapping the given range, or <code>null</code>
     */
    private Position[] findPosition(int offset, int length, Position[] positions) {

        if (positions.length == 0)
            return null;

        int rangeEnd = offset + length;
        int left = 0;
        int right = positions.length - 1;
        int mid = 0;
        Position position = null;

        while (left < right) {

            mid = (left + right) / 2;

            position = positions[mid];
            if (rangeEnd < position.getOffset()) {
                if (left == mid)
                    right = left;
                else
                    right = mid - 1;
            } else if (offset > (position.getOffset() + position.getLength() - 1)) {
                if (right == mid)
                    left = right;
                else
                    left = mid + 1;
            } else {
                left = right = mid;
            }
        }

        List list = new ArrayList();
        int index = left - 1;
        if (index >= 0) {
            position = positions[index];
            while (index >= 0 && (position.getOffset() + position.getLength()) > offset) {
                index--;
                if (index > 0) {
                    position = positions[index];
                }
            }
        }
        index++;
        position = positions[index];
        while (index < positions.length && (position.getOffset() < rangeEnd)) {
            list.add(position);
            index++;
            if (index < positions.length) {
                position = positions[index];
            }
        }

        if (list.isEmpty()) {
            return null;
        }
        return (Position[]) list.toArray(new Position[list.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.custom.LineBackgroundListener#lineGetBackground(org.eclipse.swt.custom.LineBackgroundEvent)
     */
    public void lineGetBackground(LineBackgroundEvent event) {
        event.lineBackground = null;
    }

    /**
     * Returns the hand cursor.
     * 
     * @return the hand cursor
     */
    protected Cursor getHandCursor() {
        if (handCursor == null) {
            handCursor = new Cursor(ConsolePlugin.getStandardDisplay(), SWT.CURSOR_HAND);
        }
        return handCursor;
    }

    /**
     * Returns the text cursor.
     * 
     * @return the text cursor
     */
    protected Cursor getTextCursor() {
        if (textCursor == null) {
            textCursor = new Cursor(ConsolePlugin.getStandardDisplay(), SWT.CURSOR_IBEAM);
        }
        return textCursor;
    }

    /**
     * Notification a hyperlink has been entered.
     * 
     * @param link
     *            the link that was entered
     */
    protected void linkEntered(IHyperlink link) {
        Control control = getTextWidget();
        if (hyperlink != null) {
            linkExited(hyperlink);
        }
        hyperlink = link;
        hyperlink.linkEntered();
        control.setCursor(getHandCursor());
        control.redraw();
        control.addMouseListener(this);
    }

    /**
     * Notification a link was exited.
     * 
     * @param link
     *            the link that was exited
     */
    protected void linkExited(IHyperlink link) {
        link.linkExited();
        hyperlink = null;
        Control control = getTextWidget();
        control.setCursor(getTextCursor());
        control.redraw();
        control.removeMouseListener(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseEnter(MouseEvent e) {
        getTextWidget().addMouseMoveListener(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseExit(MouseEvent e) {
        getTextWidget().removeMouseMoveListener(this);
        if (hyperlink != null) {
            linkExited(hyperlink);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseHover(MouseEvent e) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseMove(MouseEvent e) {
        int offset = -1;
        try {
            Point p = new Point(e.x, e.y);
            offset = getTextWidget().getOffsetAtLocation(p);
        } catch (IllegalArgumentException ex) {
            // out of the document range
        }
        updateLinks(offset);
    }

    /**
     * The cursor has just be moved to the given offset, the mouse has hovered
     * over the given offset. Update link rendering.
     * 
     * @param offset
     */
    protected void updateLinks(int offset) {
        if (offset >= 0) {
            IHyperlink link = getHyperlink(offset);
            if (link != null) {
                if (link.equals(hyperlink)) {
                    return;
                }
                linkEntered(link);
                return;
            }
        }
        if (hyperlink != null) {
            linkExited(hyperlink);
        }
    }

    /**
     * Returns the currently active hyperlink or <code>null</code> if none.
     * 
     * @return the currently active hyperlink or <code>null</code> if none
     */
    public IHyperlink getHyperlink() {
        return hyperlink;
    }

    /**
     * Returns the hyperlink at the specified offset, or <code>null</code> if
     * none.
     * 
     * @param offset
     *            offset at which a hyperlink has been requested
     * @return hyperlink at the specified offset, or <code>null</code> if none
     */
    public IHyperlink getHyperlink(int offset) {
        if (offset >= 0 && console != null) {
            return console.getHyperlink(offset);
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseDoubleClick(MouseEvent e) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseDown(MouseEvent e) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseUp(MouseEvent e) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.text.TextViewer#createDocumentAdapter()
     */
    protected IDocumentAdapter createDocumentAdapter() {
        if (documentAdapter == null) {
            documentAdapter = new ConsoleDocumentAdapter(consoleWidth = -1);
        }
        return documentAdapter;
    }

    /**
     * Sets the console to have a fixed character width. Use -1 to indicate that
     * a fixed width should not be used.
     * 
     * @param width
     *            fixed character width of the console, or -1
     */
    public void setConsoleWidth(int width) {
        if (consoleWidth != width) {
            consoleWidth = width;
            ConsolePlugin.getStandardDisplay().asyncExec(new Runnable() {
                public void run() {
                    if (documentAdapter != null) {
                        documentAdapter.setWidth(consoleWidth);
                    }
                }
            });
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.text.TextViewer#handleDispose()
     */
    protected void handleDispose() {
        IDocument document = getDocument();
        if (document != null) {
            document.removeDocumentListener(documentListener);
            document.removePositionUpdater(positionUpdater);
        }

        StyledText styledText = getTextWidget();
        styledText.removeLineStyleListener(this);
        styledText.removeLineBackgroundListener(this);
        styledText.removeMouseTrackListener(this);

        handCursor = null;
        textCursor = null;
        hyperlink = null;
        console = null;

        ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
        colorRegistry.removeListener(propertyChangeListener);
        
        super.handleDispose();
    }

    class HyperlinkColorChangeListener implements IPropertyChangeListener {
        public void propertyChange(PropertyChangeEvent event) {
            if (event.getProperty().equals(JFacePreferences.ACTIVE_HYPERLINK_COLOR) || event.getProperty().equals(JFacePreferences.HYPERLINK_COLOR)) {
                getTextWidget().redraw();
            }
        }

    }

    /*
     * work around to memory leak in TextViewer$WidgetCommand
     */
    protected void updateTextListeners(WidgetCommand cmd) {
        super.updateTextListeners(cmd);
        cmd.preservedText = null;
        cmd.event = null;
        cmd.text = null;
    }

    protected void internalRevealRange(int start, int end) {
        StyledText textWidget = getTextWidget();
        int startLine = documentAdapter.getLineAtOffset(start);
        int endLine = documentAdapter.getLineAtOffset(end);

        int top = textWidget.getTopIndex();
        if (top > -1) {
            // scroll vertically
            int lines = getVisibleLinesInViewport();
            int bottom = top + lines;

            // two lines at the top and the bottom should always be left
            // if window is smaller than 5 lines, always center position is
            // chosen
            int bufferZone = 2;
            if (startLine >= top + bufferZone && startLine <= bottom - bufferZone && endLine >= top + bufferZone && endLine <= bottom - bufferZone) {

                // do not scroll at all as it is already visible
            } else {
                int delta = Math.max(0, lines - (endLine - startLine));
                textWidget.setTopIndex(startLine - delta / 3);
                updateViewportListeners(INTERNAL);
            }

            // scroll horizontally
            if (endLine < startLine) {
                endLine += startLine;
                startLine = endLine - startLine;
                endLine -= startLine;
            }

            int startPixel = -1;
            int endPixel = -1;

            if (endLine > startLine) {
                // reveal the beginning of the range in the start line
                IRegion extent = getExtent(start, start);
                startPixel = extent.getOffset() + textWidget.getHorizontalPixel();
                endPixel = startPixel;
            } else {
                IRegion extent = getExtent(start, end);
                startPixel = extent.getOffset() + textWidget.getHorizontalPixel();
                endPixel = startPixel + extent.getLength();
            }

            int visibleStart = textWidget.getHorizontalPixel();
            int visibleEnd = visibleStart + textWidget.getClientArea().width;

            // scroll only if not yet visible
            if (startPixel < visibleStart || visibleEnd < endPixel) {
                // set buffer zone to 10 pixels
                bufferZone = 10;
                int newOffset = visibleStart;
                int visibleWidth = visibleEnd - visibleStart;
                int selectionPixelWidth = endPixel - startPixel;

                if (startPixel < visibleStart)
                    newOffset = startPixel;
                else if (selectionPixelWidth + bufferZone < visibleWidth)
                    newOffset = endPixel + bufferZone - visibleWidth;
                else
                    newOffset = startPixel;

                float index = ((float) newOffset) / ((float) getAverageCharWidth());

                textWidget.setHorizontalIndex(Math.round(index));
            }

        }
    }

}
