/*******************************************************************************
* Copyright (c) 2007 IONA Technologies PLC
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* 
* Contributors:
*     IONA Technologies PLC - initial API and implementation
*******************************************************************************/
package org.eclipse.stp.sc.common.internal.viewers;

import java.util.Iterator;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.stp.common.logging.LoggingProxy;
import org.eclipse.stp.sc.common.CommonPlugin;
import org.eclipse.stp.sc.common.internal.model.RuntimeCore;
import org.eclipse.stp.sc.common.views.AnnotationView;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.wst.server.core.IModuleType;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.ui.internal.Messages;
import org.eclipse.wst.server.ui.internal.viewers.RuntimeComposite;
import org.eclipse.wst.server.ui.internal.viewers.RuntimeTableLabelProvider;



/**
 * the runtime composite. which will list all stp related runtime instance installed in the system
 * has check box to show default runtime
 * @author jma
 *
 */
public class StpRuntimeCheckComposite extends StpRuntimeComposite {
	
	private static final LoggingProxy LOG = LoggingProxy.getlogger(StpRuntimeCheckComposite.class);
	
	private static final String DEFAULT_PREFIX = "default";
	
	public StpRuntimeCheckComposite(Composite parent, int style, SelectionListener listener2, 
			String[] moduleTypes) {
		super(parent, style, listener2, moduleTypes);
        ((CheckboxTableViewer)tableViewer).addCheckStateListener(new DefaultCheckStateListener());
        setCheckState((CheckboxTableViewer)tableViewer);
		
		//repack
		if (table.getItemCount() > 0) {
			TableColumn[] columns = table.getColumns();
			for (int i=0; i < columns.length; i++)
				columns[i].pack();
			table.pack();
		}
		
		
	}
	
	
	
	protected void createTableViewer() {
		tableViewer = new CheckboxTableViewer(table);
	}
	
	/**
	 * override the createTable method to create table with checkbox
	 */
	protected void createTable() {
        table = new Table(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.CHECK);
	}
	
	
	/**
	 * set the check state if it is default runtime for a module type
	 * @param viewer
	 */
    protected void setCheckState(CheckboxTableViewer viewer) {
    	IPreferenceStore store = CommonPlugin.getDefault().getPreferenceStore();
        for (int i = 0 ; i < table.getItemCount(); i++) {
            IRuntime runtime = (IRuntime) viewer.getElementAt(i);
            String moduleType = runtime.getRuntimeType().getModuleTypes()[0].getId();
            String defaultRuntimeId = store.getString(
            		DEFAULT_PREFIX + moduleType);
            if (runtime.getId().equals(defaultRuntimeId)) {
            	viewer.setChecked(runtime, true);
            } else {
            	viewer.setChecked(runtime, false);
            }
        }
	}
	
    
    /**
     * this method is called when user add or remove a runtime. it will update default runtime
     * for each module type
     * <li>when add a new runtime, if the default runtime is not set for that kind of module,
     * then set the newly added runtime as default </li>
     */
    public void updateDefault(IRuntime removeRuntime) {
    	if (removeRuntime != null) {
    		String moduleType = removeRuntime.getRuntimeType().getModuleTypes()[0].getId();
    		IPreferenceStore store = CommonPlugin.getDefault().getPreferenceStore();
    		String defaultRuntime = store.getString(DEFAULT_PREFIX + moduleType);
    		if (defaultRuntime.equals(removeRuntime.getId())) {
    			store.setValue(DEFAULT_PREFIX + moduleType, ""); 
    		}
    	}
    	
    	int items = table.getItemCount();
		for (int index = 0 ; index < items; index++ ) {
			IRuntime rt = (IRuntime)tableViewer.getElementAt(index);
			String moduleType = rt.getRuntimeType().getModuleTypes()[0].getId();
            if (isDefaultRuntimeExists(moduleType)) {
            	continue; //the default runtime for this module exists. do nothing
            }
	    	//until here, we can set this runtime to default
            selectDefaultRuntime(rt);
		}
    	
    }
    
    /**
     * check to see if the default runtime for a module type exists or not
     * @param moduleType
     * @return
     */
    protected boolean isDefaultRuntimeExists(String moduleType) {
    	IPreferenceStore store = CommonPlugin.getDefault().getPreferenceStore();
    	String defaultRuntimeId = store.getString(
        		DEFAULT_PREFIX + moduleType);
    	if (defaultRuntimeId == null || defaultRuntimeId.equals("")) {
    		return false;
    	}
    	int items = table.getItemCount();
		for (int index = 0 ; index < items; index++ ) {
			IRuntime rt = (IRuntime)tableViewer.getElementAt(index);
			if (rt.getId().equals(defaultRuntimeId)) {
				return true;
			}
		}
		//until here. the runtime doesn't exists, need to remove from preference store
		store.setValue(DEFAULT_PREFIX + moduleType, null);
		return false;
    }
    
    protected void selectDefaultRuntime(IRuntime runtime) {
    	String moduleType = runtime.getRuntimeType().getModuleTypes()[0].getId();
		IPreferenceStore store = CommonPlugin.getDefault().getPreferenceStore();
		store.setValue(DEFAULT_PREFIX
				+ moduleType, runtime.getId());
		LOG.debug("set default runtime for " + moduleType + " runtime id:" + runtime.getId());
		
		int items = table.getItemCount();
		for (int index = 0 ; index < items; index++ ) {
			IRuntime rt = (IRuntime)tableViewer.getElementAt(index);
			if (rt.getId() == runtime.getId()) {
				//same runtime
				if (!((CheckboxTableViewer)tableViewer).getChecked(rt)) {
				    ((CheckboxTableViewer)tableViewer).setChecked(rt, true);
				}
				continue;
			}
			if (supportSameModule(rt, runtime)) {
				//we only allow one default runtime for each module type
				if (((CheckboxTableViewer)tableViewer).getChecked(rt)) {
					LOG.debug("unselect previous default runtime:" + rt.getId());
					((CheckboxTableViewer)tableViewer).setChecked(rt, false);
				}
			}
		}
    }
    
    /**
	 * check to see if two runtime support same module
	 * @param rt1
	 * @param rt2
	 * @return
	 */
	private boolean supportSameModule(IRuntime rt1, IRuntime rt2) {
        IModuleType[] types  = rt1.getRuntimeType().getModuleTypes();
        for (IModuleType type1 : types) {
        	for (IModuleType type2 : rt2.getRuntimeType().getModuleTypes()) {
        		if (type1.getId().equals(type2.getId())) {
        			return true;
        		}
        	}
        }
        return false;
        	
	}
	public class DefaultCheckStateListener implements ICheckStateListener {
		public void checkStateChanged(CheckStateChangedEvent event) {
			boolean checked = event.getChecked();
			IRuntime runtime = (IRuntime)event.getElement();
	        LOG.debug("runtime selected:" + runtime.getId());
			if (checked) {
				selectDefaultRuntime(runtime);
			} 
			
		}
		
		
	}
	
}
