/*
 * Copyright 2006 Maskat Project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.maskat.framework.screendef;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.maskat.framework.IBasicDefVisitor;
import org.maskat.framework.eventdef.IEventDefSource;

public class LayoutDef extends ContainerDef {

	private String objs = "";

	private String refParentHTML;

	private IEventDefSource layoutEvtDefSrc;

	private MaskatDef maskatDef;

	/**
	 * レイアウトにないコンポーネント名前をcompに与える
	 * 同じ名前がある場合、compの名前の後ろに数字を加え。例えば：txtNew1、rdoNew21
	 * 
	 * @param comp
	 */
	public void setAppropriateNameForComponent(IComponentDef comp) {
		String originalName = comp.getName();

		BasicDefVisitorForSimilarName visitor = new BasicDefVisitorForSimilarName(
				originalName);
		this.accept(visitor);

		if (visitor.hasResult()) {
			int i = 1;
			String suggestName = originalName + i;
			while (visitor.resultContains(suggestName)) {
				suggestName = originalName + (++i);
			}
			comp.setName(suggestName);
		}
	}

	public IEventDefSource getLayoutEvtDefSrc() {
		return layoutEvtDefSrc;
	}

	public void setLayoutEvtDefSrc(IEventDefSource layoutEvtDefSrc) {
		this.layoutEvtDefSrc = layoutEvtDefSrc;
	}

	public LayoutDef getLayoutDef() {
		return this;
	}

	public String getRefParentHTML() {
		return refParentHTML;
	}

	public void setRefParentHTML(String refParentHTML) {
		this.refParentHTML = refParentHTML;
	}

	public MaskatDef getMaskatDef() {
		return maskatDef;
	}

	public void setMaskatDef(MaskatDef maskatDef) {
		this.maskatDef = maskatDef;
	}

	public String getObjs() {
		return objs;
	}

	public void addObjs(String objs) {
		this.objs += objs + ",";// 「a,b,c,d,」 + 「e,f」 + 「,」
	}

	/**
	 * Read the radio group data, set the group properties of the corresponding
	 * radio.
	 */
	public void unpackRadioGroup() {
		Iterator it = this.getTypedChildren(RadioGroupDef.class);
		if (it == null)
			return;

		final Map nameToGroupMap = new HashMap();
		while (it.hasNext()) {
			RadioGroupDef rg = (RadioGroupDef) it.next();
			String groupName = rg.getName();

			Iterator memberIt = rg.getTypedChildren(RadioMemberDef.class);
			while (memberIt != null && memberIt.hasNext()) {
				// Get the groupMember defs
				RadioMemberDef member = (RadioMemberDef) memberIt.next();
				if (member.getRef() != null)
					nameToGroupMap.put(member.getRef(), groupName);
			}
		}
		// Find all the radiodef in this layout, then set groupName
		// to the group property.
		if (nameToGroupMap.size() > 0) {
			this.accept(new IBasicDefVisitor() {
				public void visit(Object def) {
					if (def instanceof RadioDef) {
						RadioDef radioDef = (RadioDef) def;
						radioDef
								.setGroup((String) nameToGroupMap.get(radioDef.getName()));
					}
				}
			});
		}
		// this.removeAllByType(RadioGroupDef.class);
	}

	/**
	 * Delete all the "empty" radio group node
	 */
	public void packRadioGroup() {
		final Map radioGroupMap = new HashMap();
		for (Iterator it = this.getTypedChildren(RadioGroupDef.class); it != null
				&& it.hasNext();) {
			RadioGroupDef rgDef = (RadioGroupDef) it.next();
			rgDef.removeAllByType(RadioMemberDef.class);
			radioGroupMap.put(rgDef.getName(), rgDef);
			// layoutDefにすでにあるradioGroupをmapに入れる
		}

		this.accept(new IBasicDefVisitor() {
			public void visit(Object def) {
				if (def instanceof RadioDef) {
					// Create or modify a radioGroup according to the group of
					// the radio
					RadioDef radioDef = (RadioDef) def;
					String group = radioDef.getGroup();
					if (group == null || "".equals(group))
						return;
					RadioGroupDef radioGroup = (RadioGroupDef) radioGroupMap.get(group);
					if (radioGroup == null) {
						radioGroup = new RadioGroupDef();
						radioGroup.setName(group);
						radioGroupMap.put(group, radioGroup);
					}
					radioGroup.addMember(radioDef.getName());
				}
			}
		});

		// Delete all the "empty" radio group node
		List radioGroupToDel = new ArrayList();
		for (Iterator it = this.getTypedChildren(RadioGroupDef.class); it != null
				&& it.hasNext();) {
			RadioGroupDef rgDef = (RadioGroupDef) it.next();
			Iterator rgChildIt = rgDef.getAllChildren();
			if (rgChildIt == null || !rgChildIt.hasNext()) {
				radioGroupToDel.add(rgDef);
			}
		}

		for (int i = 0; i < radioGroupToDel.size(); i++) {
			this.removeChild(radioGroupToDel.get(i));
		}
	}

	public RadioGroupDef findRadioGroupDef(String group) {
		for (Iterator it = this.getTypedChildren(RadioGroupDef.class); it != null
				&& it.hasNext();) {
			RadioGroupDef rgd = (RadioGroupDef) it.next();
			if (rgd.getName() != null && rgd.getName().equals(group)) {
				return rgd;
			}
		}
		return null;
	}

	public RadioGroupDef createRadioGroupDef(String group) {
		RadioGroupDef newOne = new RadioGroupDef();
		newOne.setName(group);
		this.addChildToIdx(newOne, 0);
		return newOne;
	}

	public void removeRadioMemberFromGroup(String groupName, String memberName) {
		if (groupName == null || memberName == null)
			return;
		RadioGroupDef rgd = findRadioGroupDef(groupName);
		if (rgd == null)
			return;
		RadioMemberDef rmd = null;
		for (Iterator it = rgd.getTypedChildren(RadioMemberDef.class); it != null
				&& it.hasNext();) {
			rmd = (RadioMemberDef) it.next();
			if (memberName.equals(rmd.getRef())) {
				break;
			}
		}
		if (rmd != null)
			rgd.removeChild(rmd);
	}
}