package net.sourceforge.ganttproject.chart.overview;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.RenderedImage;
import java.util.Date;
import java.util.List;

import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;

import net.sourceforge.ganttproject.ChartComponentBase;
import net.sourceforge.ganttproject.action.GPAction;
import net.sourceforge.ganttproject.action.OkAction;
import net.sourceforge.ganttproject.action.ZoomInAction;
import net.sourceforge.ganttproject.action.ZoomOutAction;
import net.sourceforge.ganttproject.chart.BackgroundRendererImpl;
import net.sourceforge.ganttproject.chart.Chart;
import net.sourceforge.ganttproject.chart.ChartViewState;
import net.sourceforge.ganttproject.chart.TimelineChart;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.gui.zoom.ZoomManager;
import net.sourceforge.ganttproject.gui.zoom.ZoomManager.ZoomState;
import net.sourceforge.ganttproject.task.TaskLength;
import net.sourceforge.ganttproject.task.TaskManager;
import net.sourceforge.ganttproject.time.TimeUnit;
import net.sourceforge.ganttproject.time.TimeUnitFunctionOfDate;
import net.sourceforge.ganttproject.time.TimeUnitStack;
import net.sourceforge.ganttproject.time.gregorian.GPTimeUnitStack;

public class OverviewPaneAction extends GPAction {
    private final UIFacade myUIFacade;
    private JComponent myAnchorButton;
    private final ZoomInAction myZoomInAction;
    private final ZoomOutAction myZoomOutAction;
    private static final int OVERVIEW_PANE_WIDTH = 600; 
    private static final int OVERVIEW_PANE_HEIGHT = 50; 
    public OverviewPaneAction(UIFacade uiFacade) {
        super("overview");
        myUIFacade = uiFacade;
        myZoomInAction = new ZoomInAction(uiFacade.getZoomManager(), "16");
        myZoomOutAction = new ZoomOutAction(uiFacade.getZoomManager(), "16");
    }

    public void setAnchor(JComponent anchor) {
        myAnchorButton = anchor;
    }
    @Override
    protected String getLocalizedName() {
        return "Overview";
    }


    @Override
    protected String getIconFilePrefix() {
        return null;
    }

    public void actionPerformed(ActionEvent e) {
        final TimelineChart activeChart = (TimelineChart) myUIFacade.getActiveChart();
        Action okAction = new OkAction() {
            public void actionPerformed(ActionEvent e) {
            }
        };
        final GPTimeUnitStack timeunitStack = (GPTimeUnitStack) activeChart.getProject().getTimeUnitStack();
        final TimelineChart copy = (TimelineChart) activeChart.createCopy();
        final Date startDate = activeChart.getProject().getTaskManager().getProjectStart(); 
        TaskLength projectLength = activeChart.getProject().getTaskManager().getProjectLength();
        if (projectLength.getLength(timeunitStack.YEAR.createTimeUnit(startDate))<1) {
            projectLength = activeChart.getProject().getTaskManager().createLength(timeunitStack.YEAR.createTimeUnit(startDate), 1);
        }
        //ZoomState zoomState = findGoodZoomState(timeunitStack, projectLength, 600);
        TimeUnit bottomUnit = timeunitStack.MONTH.createTimeUnit(startDate);
        copy.setTopUnit(bottomUnit);
        copy.setBottomUnit(timeunitStack.DAY);
        copy.setStartDate(startDate);
        copy.setBottomUnitWidth(4);
        copy.resetRenderers();
        final OverviewRendererImpl overviewRenderer = new OverviewRendererImpl(copy.getModel());
        BackgroundRendererImpl backgroundRenderer = new BackgroundRendererImpl(copy.getModel());
        overviewRenderer.setStartDate(activeChart.getStartDate());
        overviewRenderer.setEndDate(activeChart.getEndDate());
        copy.addRenderer(backgroundRenderer);
        copy.addRenderer(overviewRenderer);
        
        class ChartPanel extends JPanel implements MenuKeyListener {
            public void menuKeyPressed(MenuKeyEvent e) {
                keyPressed(e);
            }

            public void menuKeyReleased(MenuKeyEvent e) {
            }

            public void menuKeyTyped(MenuKeyEvent arg0) {
            }
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT: {
                    activeChart.scrollRight();
                    overviewRenderer.setStartDate(activeChart.getStartDate());
                    overviewRenderer.setEndDate(activeChart.getEndDate());
                    repaint();
                    break;
                }
                case KeyEvent.VK_RIGHT: {
                    activeChart.scrollLeft();
                    overviewRenderer.setStartDate(activeChart.getStartDate());
                    overviewRenderer.setEndDate(activeChart.getEndDate());
                    repaint();
                    break;
                }
                case KeyEvent.VK_PAGE_DOWN: {
                    activeChart.setStartDate(overviewRenderer.getHighlightedEndDate());
                    overviewRenderer.setStartDate(activeChart.getStartDate());
                    overviewRenderer.setEndDate(activeChart.getEndDate());
                    repaint();
                    break;
                }
                case KeyEvent.VK_PAGE_UP: {
                    while (activeChart.getEndDate().after(overviewRenderer.getHighlightedStartDate())) {
                        activeChart.scrollRight();
                    }
                    overviewRenderer.setStartDate(activeChart.getStartDate());
                    overviewRenderer.setEndDate(activeChart.getEndDate());
                    repaint();
                    break;
                }
                case KeyEvent.VK_EQUALS: {
                    if (e.isControlDown()) {
                        myZoomInAction.actionPerformed(null);
                        overviewRenderer.setStartDate(activeChart.getStartDate());
                        overviewRenderer.setEndDate(activeChart.getEndDate());
                        repaint();
                    }
                    break;
                }
                case KeyEvent.VK_MINUS: {
                    if (e.isControlDown()) {
                        myZoomOutAction.actionPerformed(null);
                        overviewRenderer.setStartDate(activeChart.getStartDate());
                        overviewRenderer.setEndDate(activeChart.getEndDate());
                        repaint();
                    }
                    break;
                }
                }
            }
            
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                copy.setDimensions(getHeight(), getWidth());
                copy.paintChart(g);
            }
        }
        final JPanel chartPanel = new ChartPanel();
        chartPanel.setPreferredSize(new Dimension(OVERVIEW_PANE_WIDTH, OVERVIEW_PANE_HEIGHT));
        chartPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                Date result = copy.getModel().getDateAt(e.getX());
                activeChart.setStartDate(result);
                overviewRenderer.setStartDate(activeChart.getStartDate());
                overviewRenderer.setEndDate(activeChart.getEndDate());
                System.err.println("start date="+activeChart.getStartDate()+" end date="+activeChart.getEndDate());
                chartPanel.repaint();
            }
        });
        chartPanel.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {                
                Date currentDate = copy.getModel().getDateAt(e.getX());
                chartPanel.setToolTipText(currentDate.toLocaleString());
            }
        });
        chartPanel.setBorder(BorderFactory.createEtchedBorder());
        
        Component source = myAnchorButton;
        Point locButton = source.getLocationOnScreen();
        
        Component invoker = (Component)myUIFacade.getActiveChart().getAdapter(Component.class);
        Point locChart = invoker.getLocationOnScreen();
        myUIFacade.showPopupMenu(invoker, chartPanel, locButton.x - locChart.x, locButton.y+source.getHeight()-locChart.y);
    }
    
    private ZoomState findGoodZoomState(TimeUnitStack timeUnitStack, TaskLength projectLength, int chartWidth) {
        List<ZoomManager.ZoomState> zoomStates = ZoomManager.calculateZoomStates(timeUnitStack);
        for (ZoomState nextState : zoomStates) {
            float unitsCount = chartWidth/nextState.getBottomUnitWidth();
            if (!projectLength.getTimeUnit().isConstructedFrom(nextState.getTimeUnitPair().getTopTimeUnit())) {
                continue;
            }
            if (projectLength.getLength(nextState.getTimeUnitPair().getTopTimeUnit())<unitsCount) {
                return nextState;
            }
        }
        return zoomStates.get(zoomStates.size()-1);
    }

}
