package name.abuchen.portfolio.ui.util.viewers;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;

import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;

import name.abuchen.portfolio.money.Values;

public abstract class SharesLabelProvider extends OwnerDrawLabelProvider
{
    private static final char POINT = new DecimalFormatSymbols().getDecimalSeparator();

    private final NumberFormat format = new DecimalFormat("#,##0.###"); //$NON-NLS-1$

    private ColumnViewer viewer;
    private TextLayout cachedTextLayout;

    public Color getForeground(Object element)
    {
        return null;
    }

    public Color getBackground(Object element)
    {
        return null;
    }

    public abstract Long getValue(Object element);

    @Override
    public String getToolTipText(Object element)
    {
        Long value = getValue(element);
        return value != null ? Values.Share.format(value) : null;
    }

    private TextLayout getSharedTextLayout(Display display)
    {
        if (this.cachedTextLayout == null)
        {
            int orientation = this.viewer.getControl().getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
            this.cachedTextLayout = new TextLayout(display);
            this.cachedTextLayout.setOrientation(orientation);
        }
        return this.cachedTextLayout;
    }

    @Override
    protected void initialize(ColumnViewer viewer, ViewerColumn column)
    {
        this.viewer = viewer;
        super.initialize(viewer, column);
    }

    private Rectangle getSize(Event event, String text)
    {
        String s = text;
        int p = s.indexOf(POINT);
        if (p >= 0)
            s = s.substring(0, p);

        TextLayout textLayout = getSharedTextLayout(event.display);
        textLayout.setText(s + ",000"); //$NON-NLS-1$

        return textLayout.getBounds();
    }

    private Rectangle getBounds(Widget widget, int index)
    {
        if (widget instanceof TableItem)
            return ((TableItem) widget).getBounds(index);
        else if (widget instanceof TreeItem)
            return ((TreeItem) widget).getBounds(index);
        else
            throw new IllegalArgumentException();
    }

    @Override
    protected void measure(Event event, Object element)
    {
        Long value = getValue(element);
        if (value != null)
        {
            String text = format.format(value / Values.Share.divider());
            Rectangle size = getSize(event, text);

            Rectangle tableItem = getBounds(event.item, event.index);

            int width = Math.min(size.width, tableItem.width);

            event.setBounds(new Rectangle(event.x + tableItem.width - width, event.y, //
                            width, event.height));
        }
    }

    @Override
    protected void paint(Event event, Object element)
    {
        Rectangle tableItem = getBounds(event.item, event.index);
        boolean isSelected = (event.detail & SWT.SELECTED) != 0 || (event.detail & SWT.HOT) != 0;

        if (!isSelected)
            fillBackground(event, element, tableItem);

        Long value = getValue(element);
        if (value == null)
            return;

        Color oldForeground = null;
        Color newForeground = isSelected ? null : getForeground(element);
        if (newForeground != null)
        {
            oldForeground = event.gc.getForeground();
            event.gc.setForeground(newForeground);
        }

        String text = format.format(value / Values.Share.divider());
        Rectangle size = getSize(event, text);

        TextLayout textLayout = getSharedTextLayout(event.display);
        textLayout.setText(text);

        Rectangle layoutBounds = textLayout.getBounds();
        int x = event.x + tableItem.width - Math.min(size.width, tableItem.width);
        int y = tableItem.y + Math.max(0, (tableItem.height - layoutBounds.height) / 2);

        textLayout.draw(event.gc, x, y);

        if (oldForeground != null)
            event.gc.setForeground(oldForeground);
    }

    private void fillBackground(Event event, Object element, Rectangle bounds)
    {
        Color newBackground = getBackground(element);
        if (newBackground != null)
        {
            Color oldBackground = event.gc.getBackground();
            event.gc.setBackground(newBackground);
            event.gc.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height);
            event.gc.setBackground(oldBackground);
        }
    }

    @Override
    protected void erase(Event event, Object element)
    {
        // use os-specific background
    }
}

@@ -4302,25 +4302,21 @@
 int y = 
-tableItem
+event
 .y + Mat

Fix invisible cells in 'Shares' column on linux