//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   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 de.ugoe.cs.autoquest.eventcore.guimodel;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * This class is a dummy GUI element to represent groups of GUI elements. A group of GUI elements
 * can be integrated in any GUI model using the method
 * {@link GUIModel#groupGUIElements(java.util.List, String)}. A group has the same behavior as
 * any other parent GUI element.
 * </p>
 * 
 * @author Patrick Harms
 */
public class GUIElementGroup extends AbstractDefaultGUIElement {

    /**
     * <p>
     * default serial version UID
     * </p>
     */
    private static final long serialVersionUID = 1L;
    
    /**
     * the list of grouped GUIElements
     */
    private List<IGUIElement> groupedGUIElements = new LinkedList<IGUIElement>();

    /**
     * <p>
     * instantiates a GUI element group with a name and its optional parent GUI element
     * </p>
     *
     * @param groupName the name of the GUI element group
     * @param parent    the optional parent GUI element of the group
     * @param guiModel  the GUI model to which the group will belong
     */
    public GUIElementGroup(String groupName, IGUIElement parent, GUIModel guiModel) {
        super(new GroupSpecification(groupName), parent);
        super.setGUIModel(guiModel);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#updateSpecification(IGUIElementSpec)
     */
    @Override
    public final void updateSpecification(IGUIElementSpec furtherSpec) {
        // do nothing
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.eventcore.IEventTarget#getPlatform()
     */
    @Override
    public String getPlatform() {
        return "none";
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.eventcore.IEventTarget#getStringIdentifier()
     */
    @Override
    public String getStringIdentifier() {
        return ((GroupSpecification) super.getSpecification()).name;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return getStringIdentifier();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getDistanceTo(IGUIElement)
     */
    @Override
    public double getDistanceTo(IGUIElement otherElement) {
        if (equals(otherElement)) {
            return 0.0;
        }
        else if (super.getParent() != null) {
            return super.getParent().getDistanceTo(otherElement);
        }
        else {
            return 1.0;
        }
    }

    /**
     * <p>
     * returns the list of GUI elements belonging to this group.
     * </p>
     * 
     * @return the GUI elements belonging to this group
     * 
     */
    public List<IGUIElement> getGroupedElements() {
        return Collections.unmodifiableList(groupedGUIElements);
    }
    
    /**
     * <p>
     * allows adding a new GUI element to the group
     * </p>
     *
     * @param guiElement the new member of the group
     */
    void addToGroup(IGUIElement guiElement) {
        this.groupedGUIElements.add(guiElement);
    }
    
    /**
     * <p>
     * internally required GUI element specification for a GUI element group. This is just a wrapper
     * for a name of a GUI element group
     * </p>
     * 
     * @author Patrick Harms
     */
    private static class GroupSpecification implements IGUIElementSpec {
        
        /**
         * <p>
         * default serial version UID
         * </p>
         */
        private static final long serialVersionUID = 1L;
        
        /**
         * <p>
         * the name of the GUI element group represented by this specification
         * </p>
         */
        private String name;

        /**
         * <p>
         * instantiates the group specification with the given name. Two group specifications
         * are only similar, if their names match.
         * </p>
         *
         * @param name the name of the group
         */
        private GroupSpecification(String name) {
            super();
            this.name = name;
        }

        /* (non-Javadoc)
         * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getType()
         */
        @Override
        public String getType() {
            return "GUI element group";
        }

        /* (non-Javadoc)
         * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getTypeHierarchy()
         */
        @Override
        public String[] getTypeHierarchy() {
            return new String[] { getType() };
        }

        /* (non-Javadoc)
         * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getSimilarity(IGUIElementSpec)
         */
        @Override
        public boolean getSimilarity(IGUIElementSpec other) {
            return
                (other instanceof GroupSpecification) &&
                name.equals(((GroupSpecification) other).name);
        }

    }

}
