package name.abuchen.portfolio.ui.views.taxonomy;

import javax.inject.Inject;

import org.apache.commons.lang3.StringEscapeUtils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import com.ibm.icu.text.MessageFormat;

import name.abuchen.portfolio.money.Money;
import name.abuchen.portfolio.money.Values;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.PortfolioPlugin;
import name.abuchen.portfolio.ui.util.EmbeddedBrowser;
import name.abuchen.portfolio.ui.util.SimpleAction;

/* package */class PieChartViewer extends AbstractChartPage
{
    private EmbeddedBrowser browser;

    @Inject
    public PieChartViewer(TaxonomyModel model, TaxonomyNodeRenderer renderer)
    {
        super(model, renderer);
    }

    @Override
    public void configMenuAboutToShow(IMenuManager manager)
    {
        super.configMenuAboutToShow(manager);

        Action action = new SimpleAction(Messages.LabelIncludeSecuritiesInPieChart, a -> {
            getModel().setExcludeSecuritiesInPieChart(!getModel().isSecuritiesInPieChartExcluded());
            onConfigChanged();
        });
        action.setChecked(!getModel().isSecuritiesInPieChartExcluded());
        manager.add(action);
    }

    @Override
    public Control createControl(Composite container)
    {
        browser = new EmbeddedBrowser("/META-INF/html/flare.html"); //$NON-NLS-1$
        return browser.createControl(container, b -> new LoadDataFunction(b, "loadData")); //$NON-NLS-1$
    }

    @Override
    public void beforePage()
    {
        // nothing to do
    }

    @Override
    public void afterPage()
    {
        // nothing to do
    }

    @Override
    public void nodeChange(TaxonomyNode node)
    {
        browser.refresh();
    }

    @Override
    public void onConfigChanged()
    {
        browser.refresh();
    }

    private final class LoadDataFunction extends BrowserFunction
    {
        private LoadDataFunction(Browser browser, String name)
        {
            super(browser, name);
        }

        @Override
        public Object function(Object[] arguments)
        {
            try
            {
                TaxonomyNode root = getModel().getChartRenderingRootNode();

                StringBuilder buffer = new StringBuilder();
                printNode(buffer, root, root.getActual(), getModel().isSecuritiesInPieChartExcluded());
                return buffer.toString();
            }
            catch (Throwable e) // NOSONAR
            {
                PortfolioPlugin.log(e);
                return "{}"; //$NON-NLS-1$
            }
        }

        @SuppressWarnings("nls")
        private void printNode(StringBuilder buffer, TaxonomyNode node, Money total, boolean excludeSecurities)
        {
            String name = StringEscapeUtils.escapeJson(node.getName());
            long actual = node.isRoot() ? total.getAmount() : node.getActual().getAmount();
            long base = node.isRoot() ? total.getAmount() : node.getParent().getActual().getAmount();

            String totalPercentage = "";
            if (node.getParent() != null && !node.getParent().isRoot())
                totalPercentage = "; " + MessageFormat.format(Messages.LabelTotalValuePercent,
                                Values.Percent2.format(actual / (double) total.getAmount()));

            if (excludeSecurities && node.isAssignment())
            {
                buffer.append("{\"name\":\"\",\"caption\":\"\",");
                buffer.append("\"value\":").append(node.getActual().getAmount());
                buffer.append(",\"color\":\"#FFFFFF\"");
            }
            else
            {
                buffer.append("{\"name\":\"").append(name);
                buffer.append("\",\"caption\":\"");
                buffer.append(name).append(" ").append(Values.Amount.format(actual)).append(" (")
                                .append(Values.Percent2.format(actual / (double) base)).append(totalPercentage)
                                .append(")\",");
                buffer.append("\"value\":").append(node.getActual().getAmount());
                buffer.append(",\"color\":\"").append(node.getColor()).append("\"");
            }

            addChildren(buffer, node, total, excludeSecurities);

            buffer.append("}");
        }

        private void addChildren(StringBuilder buffer, TaxonomyNode node, Money total, boolean excludeSecurities)
        {
            // iterate over children if
            // a) all are shown anyway or
            // b) if the children contain at least one classification (which
            // means if securities are not show we do not go over the children
            // as there are only securities)

            boolean iterateChildren = !excludeSecurities
                            || node.getChildren().stream().anyMatch(n -> !n.isAssignment());

            if (!iterateChildren)
                return;

            boolean isFirst = true;
            for (TaxonomyNode child : node.getChildren())
            {
                if (child.getActual().isZero())
                    continue;

                if (isFirst)
                    buffer.append(",\"children\": ["); //$NON-NLS-1$
                else
                    buffer.append(","); //$NON-NLS-1$

                printNode(buffer, child, total, excludeSecurities);
                isFirst = false;
            }

            if (!isFirst)
                buffer.append("]"); //$NON-NLS-1$
        }

    }
}

@@ -44,16 +44,40 @@
 onomy;%0A%0A
+import java.awt.Color;%0A%0A
 import j
@@ -2530,16 +2530,20 @@
 r, root,
+ %22%22,
  root.ge
@@ -2590,32 +2590,46 @@
 hartExcluded());
+ //$NON-NLS-1$
 %0A               
@@ -2935,36 +2935,78 @@
 yNode node, 
-Money total,
+String nodeColor, Money total,%0A                       
  boolean exc
@@ -4423,32 +4423,228 @@
 r%5C%22:%5C%22%22).append(
+%0A                                !excludeSecurities && node.isAssignment() ? colorBrighter(nodeColor) : node.getColor())%0A                                .append(%22%5C%22%22);%0A                nodeColor = 
 node.getColor())
@@ -4645,22 +4645,8 @@
 lor(
-)).append(%22%5C%22%22
 );%0A 
@@ -4696,16 +4696,33 @@
 r, node,
+ node.getColor(),
  total, 
@@ -4859,28 +4859,70 @@
 e node, 
-Money total,
+String nodeColor, Money total,%0A                       
  boolean
@@ -5846,16 +5846,27 @@
 , child,
+ nodeColor,
  total, 
@@ -6016,20 +6016,437 @@
 %0A        %7D%0A%0A
+        private String colorBrighter(String inputColor)%0A        %7B%0A            Color color = new Color(Integer.valueOf(inputColor.substring(1, 3), 16),%0A                            Integer.valueOf(inputColor.substring(3, 5), 16),%0A                            Integer.valueOf(inputColor.substring(5, 7), 16));%0A            return %22#%22 + Integer.toHexString(color.brighter().getRGB()).substring(2); //$NON-NLS-1$%0A        %7D%0A%0A
     %7D%0A%7D%0A

Update PieChartViewer.java