/**
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * Copyright © 2009 Mindoo GmbH
 *
 * @author Tammo Riedinger
 *
 */
package com.mindoo.ec09.framework.actions;

import java.awt.Container;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

public class ActionManager {
	private LinkedHashMap<String,ActionSet> m_actionSets=new LinkedHashMap<String,ActionSet>();
	private JMenuBar m_menuBar;
	private Container m_toolbarContainer;
	
	private ArrayList<ActionSet> m_currentSets=new ArrayList<ActionSet>();
	
	public ActionManager(JMenuBar menuBar, Container toolbarContainer) {
		m_menuBar=menuBar;
		m_toolbarContainer=toolbarContainer;
	}
	
	public void setMenuBar(JMenuBar menuBar) {
		m_menuBar=menuBar;
		
		setActive(getActiveSetIDs());
	}

	public void setToolbarContainer(Container toolbarContainer) {
		m_toolbarContainer=toolbarContainer;
		if (m_toolbarContainer!=null)
			m_toolbarContainer.setFocusable(false);

		setActive(getActiveSetIDs());
	}
	
	public String[] getActiveSetIDs() {
		ArrayList<String> sets=new ArrayList<String>();
		
		for (ActionSet actionSet:m_currentSets)
			sets.add(actionSet.getID());

		return sets.toArray(new String[0]);
	}

	public Iterator<Action> getActions(String setID) {
		ActionSet actionSet=m_actionSets.get(setID);
		
		if (actionSet!=null) {
			return actionSet.getActions();
		}
		else
			return new ArrayList<Action>().iterator();
	}
	
	public void registerAction(Action a, String setID, String menuName, String toolbarName) {
		if (setID!=null) {
			ActionSet actionSet=m_actionSets.get(setID);
			if (actionSet==null) {
				actionSet=new ActionSet(setID);
				m_actionSets.put(setID, actionSet);
			}
			actionSet.addAction(a, menuName, toolbarName);
		}
	}
	
	public void setActive(String... setIDs) {
		String[] curIDs=new String[m_currentSets.size()];
		int i=0;
		for (ActionSet set:m_currentSets)
			curIDs[i++]=set.getID();
		
		deActivate(curIDs);
		
		activate(setIDs);
	}
	
	public void activate(String... setIDs) {
		for (String id:setIDs) {
			ActionSet set=m_actionSets.get(id);
			
			if (set!=null) {
				addElements(set);
				
				m_currentSets.add(set);
			}
		}
	}
	
	public void deActivate(String... setIDs) {
		for (String id:setIDs) {
			ActionSet set=m_actionSets.get(id);
			
			if (set!=null) {
				removeElements(set);
				
				m_currentSets.remove(set);
			}
		}
	}
	
	private void addElements(ActionSet set) {
		if (m_menuBar!=null) {
			for (JMenu menu:set.getMenus())
				m_menuBar.add(menu);
			
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					m_menuBar.doLayout();
					
					m_menuBar.repaint();
				}
			});
		}
		
		if (m_toolbarContainer!=null) {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					m_toolbarContainer.doLayout();
					
					m_toolbarContainer.repaint();
				}
			});

			for (final JToolBar toolbar:set.getToolbars()) {
				m_toolbarContainer.add(toolbar);

				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						toolbar.doLayout();
						
						toolbar.repaint();
					}
				});

			}
		}
	}
	
	private void removeElements(ActionSet set) {
		if (m_menuBar!=null) {
			for (JMenu menu:set.getMenus())
				m_menuBar.remove(menu);
			
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					m_menuBar.doLayout();
					
					m_menuBar.repaint();
				}
			});
		}
		
		if (m_toolbarContainer!=null) {
			for (JToolBar toolbar:set.getToolbars())
				m_toolbarContainer.remove(toolbar);
			
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					m_toolbarContainer.doLayout();
					
					m_toolbarContainer.repaint();
				}
			});
		}
	}
	
	private static class ActionSet {
		private String m_id;
		private LinkedHashMap<Action, Action> m_actions=new LinkedHashMap<Action,Action>();
		private LinkedHashMap<String, ArrayList<Action>> m_menuActions=new LinkedHashMap<String,ArrayList<Action>>();
		private LinkedHashMap<String, ArrayList<Action>> m_toolbarActions=new LinkedHashMap<String,ArrayList<Action>>();
		
		private JMenu[] m_menus;
		private JToolBar[] m_toolbars;
		
		public ActionSet(String id) {
			m_id=id;
		}
		
		public String getID() {
			return m_id;
		}
		
		public void addAction(Action a, String menuName, String toolbarName) {
			m_actions.put(a,a);
			
			if (menuName!=null) {
				ArrayList<Action> menuActions=m_menuActions.get(menuName);
				if (menuActions==null) {
					menuActions=new ArrayList<Action>();
					m_menuActions.put(menuName, menuActions);
				}
				menuActions.add(a);
			}
			
			if (toolbarName!=null) {
				ArrayList<Action> toolbarActions=m_toolbarActions.get(toolbarName);
				if (toolbarActions==null) {
					toolbarActions=new ArrayList<Action>();
					m_toolbarActions.put(toolbarName, toolbarActions);
				}
				toolbarActions.add(a);
			}
		}
		
		public Iterator<Action> getActions() {
			return m_actions.values().iterator();
		}
		
		public JMenu[] getMenus() {
			if (m_menus==null) {
				m_menus=new JMenu[m_menuActions.size()];
				
				int i=0;
				for (String menuName:m_menuActions.keySet()) {
					m_menus[i]=new JMenu(menuName);
					
					for (Action a:m_menuActions.get(menuName))
						m_menus[i].add(a);
					
					i++;
				}
			}
			
			return m_menus;
		}
		
		public JToolBar[] getToolbars() {
			if (m_toolbars==null) {
				m_toolbars=new JToolBar[m_toolbarActions.size()];
				
				int i=0;
				for (String menuName:m_toolbarActions.keySet()) {
					m_toolbars[i]=new JToolBar(menuName);
					m_toolbars[i].setFocusable(false);
					m_toolbars[i].setFloatable(false);
					
					for (Action a:m_toolbarActions.get(menuName)) {
						JButton button=m_toolbars[i].add(a);
						
						button.setFocusable(false);
					}
					
					i++;
				}
			}
			
			return m_toolbars;
		}
	}
}
