/*
 * Created on 03.11.2004
 */
package net.sourceforge.ganttproject.gui.zoom;

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

import net.sourceforge.ganttproject.time.TimeUnitPair;
import net.sourceforge.ganttproject.time.TimeUnitStack;

/**
 * @author bard
 */
public class ZoomManager implements TimeUnitStack.Listener {
    public static class ZoomState {
        final TimeUnitPair myTimeUnitPair;

        final int myBottomUnitWidth;

        final private int myStateNumber;

        ZoomState(TimeUnitPair timeUnitPair, int bottomUnitWidth,
                int stateNumber) {
            myTimeUnitPair = timeUnitPair;
            myBottomUnitWidth = bottomUnitWidth;
            myStateNumber = stateNumber;
        }

        public String getPersistentName() {
            return myTimeUnitPair.getTimeUnitStack().getName() + ":"
                    + myStateNumber;
        }

        public TimeUnitPair getTimeUnitPair() {
            return myTimeUnitPair;
        }

        public int getBottomUnitWidth() {
            return myBottomUnitWidth;
        }
    }

    private int myZooming = 2;

    private List<ZoomListener> myListeners = new ArrayList<ZoomListener>();

    private TimeUnitStack myTimeUnitStack;

    private ZoomState[] myZoomStates;

    public ZoomManager(TimeUnitStack timeUnitStack) {
        myTimeUnitStack = timeUnitStack;
        myTimeUnitStack.addTimeUnitStackListener(this);
        recalculateZoomStates();
    }

    private void recalculateZoomStates() {
        myZoomStates = ZoomManager.calculateZoomStates(myTimeUnitStack).toArray(new ZoomState[0]);
    }
    public boolean canZoomIn() {
        return myZooming > 0;
    }

    public boolean canZoomOut() {
        return myZooming < myZoomStates.length - 1;
    }

    public void zoomIn() {
        int oldValue = myZooming--;
        fireZoomingChanged(oldValue, myZooming);
    }

    public void zoomOut() {
        int oldValue = myZooming++;
        fireZoomingChanged(oldValue, myZooming);
    }

    public void addZoomListener(ZoomListener listener) {
        myListeners.add(listener);
        listener.zoomChanged(new ZoomEvent(this, myZoomStates[myZooming]));
    }

    public void removeZoomListener(ZoomListener listener) {
        myListeners.remove(listener);
    }

    private void fireZoomingChanged(int oldZoomValue, int newZoomValue) {
        ZoomEvent e = new ZoomEvent(this, myZoomStates[newZoomValue]);
        for (int i = 0; i < myListeners.size(); i++) {
            ZoomListener nextListener = (ZoomListener) myListeners.get(i);
            nextListener.zoomChanged(e);
        }
    }

    public void setZoomState(String persistentName) {
        for (int i = 0; i < myZoomStates.length; i++) {
            if (myZoomStates[i].getPersistentName().equals(persistentName)) {
                myZooming = i;
                fireZoomingChanged(0, myZooming);
                break;
            }
        }
    }

    public ZoomState getZoomState() {
        return myZoomStates[myZooming];
    }
    
    public List<ZoomState> getAllZoomStates() {
    	return Arrays.asList(myZoomStates);
    }
    public int getMyZooming(){
    	return myZooming;
    }

    public void timeUnitStackChanged() {
        recalculateZoomStates();
        int oldZoom = myZooming;
        myZooming = 0;
        fireZoomingChanged(oldZoom, myZooming);
    }

    public static List<ZoomState> calculateZoomStates(TimeUnitStack timeUnitStack) {
        TimeUnitPair[] unitPairs = timeUnitStack.getTimeUnitPairs();
        List<ZoomState> result = new ArrayList<ZoomState>(unitPairs.length);
        int width1 = 60;
        int width2 = 40;
        for (int i = 0; i < unitPairs.length; i++) {
            result.add(new ZoomManager.ZoomState(unitPairs[i], width1, i));
            // myZoomStates[i*2+1] = new ZoomState(unitPairs[i], width2);
            float scale = 2f/3f;
            if (i < unitPairs.length - 1) {
                if (unitPairs[i].equals(unitPairs[i+1])) {
                    width1 = (int) ((float)width1 * scale);
                    
                }
                else {
                    width1 = 60;
                }
                
//                float defaults1 = unitPairs[i].getBottomTimeUnit()
//                        .getAtomCount(myTimeUnitStack.getDefaultTimeUnit());
//                float defaults2 = unitPairs[i + 1].getBottomTimeUnit()
//                        .getAtomCount(myTimeUnitStack.getDefaultTimeUnit());
//                scale = (2 * defaults2) / (9 * defaults1);
            }
        }        
        return result;
    }
}
