package net.sourceforge.ganttproject;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;

import net.sourceforge.ganttproject.font.Fonts;
import net.sourceforge.ganttproject.gui.UIConfiguration;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.util.TextLengthCalculatorImpl;

class TaskTreeImageGenerator {
    private GanttTree2 myTreeView;
    private UIConfiguration myUIConfiguration;
    private int myWidth;

    TaskTreeImageGenerator(GanttTree2 treeView, UIConfiguration uiConfiguration) {
        myTreeView = treeView;
        myUIConfiguration = uiConfiguration;
        
    }
    
    private GanttTree2 getTree() {
        return myTreeView;
    }
    
    List<DefaultMutableTreeTableNode> getPrintableNodes(GanttExportSettings settings) {
        List<DefaultMutableTreeTableNode> myItemsToConsider;
        if (settings.isOnlySelectedItem()) {
            myItemsToConsider = Arrays.asList(getTree().getSelectedNodes());
        }
        else {
            myItemsToConsider = getTree().getAllVisibleNodes();
        }
        System.out.println("TaskToConsider.size = " + myItemsToConsider.size());

        for (int i = 0; i < myItemsToConsider.size(); i++) {
            if (myItemsToConsider.get(i).isRoot()) {
                myItemsToConsider.remove(i);
                break;
            }
        }
        return myItemsToConsider;
        
    }
    Image createImage(List<DefaultMutableTreeTableNode> myItemsToConsider) {
        BufferedImage tmpImage = new BufferedImage(10, 10,
                BufferedImage.TYPE_INT_RGB);

        FontMetrics fmetric = tmpImage.getGraphics().getFontMetrics(
        myUIConfiguration.getChartMainFont().deriveFont(12f));
        int fourEmWidth = fmetric.stringWidth("mmmm");
        
        int width = 0;
        int height = getTree().getTreeTable().getRowHeight()*3 + HEADER_OFFSET;
        for (Iterator<DefaultMutableTreeTableNode> tasks = myItemsToConsider.iterator(); tasks.hasNext();) {
            DefaultMutableTreeTableNode nextTreeNode = tasks.next();

            Task next = (Task) nextTreeNode.getUserObject();
            if ("None".equals(next.toString())) {
                continue;
            }
            if (isVisible(next)) {
                height += getTree().getTreeTable().getRowHeight();
                int nbchar = fmetric.stringWidth(next.getName())+next.getManager().getTaskHierarchy().getDepth(next)*fourEmWidth;
                if (nbchar > width) {
                    width = nbchar;
                }
            }
        }

        width += 10;
        myWidth = width;
        
        BufferedImage image2 = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        // setSize(sizeTOC, getHeight());
        Graphics g2 = image2.getGraphics();
        ((Graphics2D) g2).setRenderingHint(
                RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setColor(Color.WHITE);
        g2.fillRect(0, 0, width, height);
        printTasks(g2, myItemsToConsider);
        
        GanttImagePanel but = new GanttImagePanel("big.png", 300, 47);
        g2.setColor(new Color(102, 153, 153));
        g2.fillRect(0,0, width, but.getHeight());
        but.paintComponent(g2);        
        return image2;
    }
    
    private int getWidth() {
        return myWidth;
    }
    
    private void printTasks(Graphics g, List<DefaultMutableTreeTableNode> taskNodes) {

        g.setColor(Color.black);

        // g.setFont(myUIConfiguration.getChartMainFont().deriveFont(12f));
        g.setFont(Fonts.PRINT_CHART_FONT);

        // JA Changed 42 to 66
        // This is related to the hardcoded headerheight
        // TODO: Fix hard-coded part
        // printTask(g,5,66,getTree().getAllChildTask(getTree().getRoot()));
        printTask(g,taskNodes);

    }

    private int printTask(Graphics g, List<DefaultMutableTreeTableNode> child) {
        int rowCount=0;
        final int h = getTree().getTreeTable().getRowHeight();
        Stack<DefaultMutableTreeTableNode> nestingStack = new Stack<DefaultMutableTreeTableNode>();
        //int x = 5;
        final int fourEmWidth = new TextLengthCalculatorImpl(g).getTextLength("mmmm");
        int y = getTree().getTable().getTableHeader().getHeight()
        + HEADER_OFFSET;
        for (Iterator<DefaultMutableTreeTableNode> tasks = child.iterator(); tasks.hasNext();) {
            DefaultMutableTreeTableNode nextTreeNode = tasks.next();

            Task next = null;
                next = (Task) nextTreeNode.getUserObject();
                while (!nestingStack.isEmpty()) {
                    DefaultMutableTreeTableNode topStackNode = nestingStack.pop();
                    if (nextTreeNode.getParent()==topStackNode) {
                        nestingStack.push(topStackNode);
                        break;
                    }
                }
                nestingStack.push(nextTreeNode);
            if (isVisible(next)) {
                if (rowCount % 2 == 1) {
                    g.setColor(new Color((float) 0.933, (float) 0.933,
                            (float) 0.933));
                    g.fillRect(0, y, getWidth() - h / 2, h);
                }
                g.setColor(Color.black);
                g.drawRect(0, y, getWidth() - h / 2, h);
                    int charH = (int) g.getFontMetrics().getLineMetrics(
                            next.getName(), g).getAscent();
                    int x = (nestingStack.size()-1)*fourEmWidth+5;
                    g.drawString(next.getName(), x, y + charH
                                    + (h - charH) / 2);


                g.setColor(new Color((float) 0.807, (float) 0.807,
                        (float) 0.807));

                g.drawLine(1, y + h-1, getWidth() - 11, y + h-1);
                y += h;

                rowCount++;

                // if (nextTreeNode.getChildCount() != 0) {
                // y = printTask(g, x + (h / 2), y, getTree().getAllChildTask(
                // nextTreeNode));
                // }
            }
        }
        return y;
    }

    
    
    private boolean isVisible(Task thetask) {
        boolean res = true;
        DefaultMutableTreeTableNode father = getTree().getFatherNode(thetask);
        if (father == null) {
            return false;
        }

        while (father != null) {
            Task taskFather = (Task) (father.getUserObject());
            if (!taskFather.getExpand()) {
                res = false;
            }
            father = (DefaultMutableTreeTableNode) (father.getParent());
        }
        return res;
    }
    
    private static final int HEADER_OFFSET = 44;
    
}
