/**
 * 
 * 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.application;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public abstract class MultiTabsApplication extends AbstractApplication {
	private Object CONTENT_PANE_KEY=new Object();
	
	@Override
	protected Container createContentPane() {
		return new JTabbedPane();
	}
	
	public int getTabCount() {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane)
			return ((JTabbedPane)contentPane).getTabCount();
		
		return 0;
	}
	
	public Container getInternalContentPane(Object userObject) {
		JComponent tab=getInternalTab(userObject);
		
		if (tab!=null)
			return getInternalContentPane(tab);
		
		return null;
	}
	
	public Container getInternalContentPane(JComponent tab) {
		if (tab!=null)
			return (Container)tab.getClientProperty(CONTENT_PANE_KEY);
		
		return null;
	}
		
	public JComponent getInternalTab(Object userObject) {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane) {
			int count=((JTabbedPane)contentPane).getTabCount();
			for (int i=0;i<count;i++) {
				JComponent tab=(JComponent)((JTabbedPane)contentPane).getComponentAt(i);
				if (userObject.equals(getUserObject(tab)))
					return tab;
			}
		}
		
		return null;
	}
	
	public Object getUserObject(JComponent tab) {
		return tab.getClientProperty(MultiTabsApplication.this);
	}

	public JComponent[] getAllInternalTabs() {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane) {
			int count=((JTabbedPane)contentPane).getTabCount();
			JComponent[] tabs=new JComponent[count];
			for (int i=0;i<count;i++)
				tabs[i]=(JComponent)((JTabbedPane)contentPane).getComponentAt(i);
			
			return tabs;
		}
		
		return new JComponent[0];
	}
	
	public JComponent getTabAt(int index) {
		if (index<0 || index>=getTabCount())
			throw new IllegalArgumentException("MultiTabsApplication: Specified index is out of range!");
		
		return getAllInternalTabs()[index];
	}
	
	public JComponent getSelectedTab() {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane)
			return (JComponent)((JTabbedPane)contentPane).getSelectedComponent();
		
		return null;
	}
	
	public void setSelectedTab(JComponent tab) {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane)
			((JTabbedPane)contentPane).setSelectedComponent(tab);
	}
	
	public void removeTab(JComponent tab) {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane) {
			int index=((JTabbedPane)contentPane).indexOfComponent(tab);
			if (index!=-1)
				((JTabbedPane)contentPane).removeTabAt(index);
		}
	}
	
	public void removeTabAt(int index) {
		Component contentPane=getContentPane();
		
		if (contentPane instanceof JTabbedPane)
			((JTabbedPane)contentPane).removeTabAt(index);
	}

	@Override
	protected void installContentPane(Component window, Container contentPane) {
		super.installContentPane(window, contentPane);
		
		if (contentPane instanceof JTabbedPane) {
			installInitialTabs();
		}
		else
			throw new RuntimeException("Unknown type of content pane");
	}

	protected void installInitialTabs() {
	}
	
	public JComponent addNewTab(String title, Object userObject, boolean select) {
		return addNewTabAt(getTabCount(), title, userObject, select);
	}
	
	public JComponent addNewTab(String title, Object userObject) {
		return addNewTab(title,userObject,true);
	}
	
	public JComponent addNewTabAt(int index, String title, Object userObject, boolean select) {
		if (index<0)
			throw new IllegalArgumentException("MultiTabsApplication: Specified index has to be greater than 0!");

		JComponent tab=createTab(title, userObject);
		
		configureTab(tab, userObject);
		
		if (index>=getTabCount()) {
			addTab(title,tab,userObject,select);
		}
		else
			addTabAt(index, title, tab, userObject, select);
		
		return tab;
	}
	
	public JComponent addNewTabAt(int index, String title, Object userObject) {
		return addNewTabAt(index, title,userObject,true);
	}
	
	protected JComponent createTab(String title, Object userObject) {
		JComponent tab=new JPanel(new BorderLayout());
  
		return tab;
	}

	protected void configureTab(JComponent tab, Object userObject) {
    	Container contentPane=createInternalContentPane(userObject);
    	
    	configureInternalContentPane(userObject, contentPane);
    	
    	tab.add(contentPane, BorderLayout.CENTER);
    	
    	tab.putClientProperty(CONTENT_PANE_KEY, contentPane);
	}

	protected Container createInternalContentPane(Object userObject) {
		return new JPanel();
	}

	protected void configureInternalContentPane(Object userObject, Container contentPane) {
	}
	
	public void addTab(String title, JComponent tab, Object userObject, boolean select) {
		addTabAt(getTabCount(), title, tab, userObject, select);
	}
	
	public void addTabAt(int index, String title, JComponent tab, Object userObject, boolean select) {
		if (index<0)
			throw new IllegalArgumentException("MultiTabsApplication: Specified index has to be greater than 0!");

		Component contentPane=getContentPane();
		
		if (!(contentPane instanceof JTabbedPane))
			throw new RuntimeException("Unknown type of content pane");
		
		tab.putClientProperty(MultiTabsApplication.this, userObject);
		
		if (index>=getTabCount()) {
			((JTabbedPane)contentPane).addTab(formatTabTitle(title), tab);
		}
		else
			((JTabbedPane)contentPane).insertTab(formatTabTitle(title), null, tab, null, index);
		
		if (select)
	    	((JTabbedPane)contentPane).setSelectedComponent(tab);
	}
	
	protected String formatTabTitle(String title) {
		if (title.length()>25)
			return "..." + title.substring(title.length()-22, title.length());
		
		return title;
	}
	
	public void setTitleAt(int index, String title) {
		if (!(contentPane instanceof JTabbedPane))
			throw new RuntimeException("Unknown type of content pane");
		
		((JTabbedPane)contentPane).setTitleAt(index, formatTabTitle(title));
	}
	
	public void addTab(String title, JComponent tab, Object userObject) {
		addTab(title, tab,userObject,true);
	}
	
	public void addTabAt(int index, String title, JComponent tab, Object userObject) {
		addTabAt(index, title, tab,userObject,true);
	}
}