/*
 * Copyright 2012 s_wolff.
 *
 * 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.aegee.runanddine.pathfinder.optimizers;

import java.util.ArrayList;
import java.util.Collection;

import org.aegee.runanddine.RunAndDineApplication;

/**
 * Works on Collections of AbstractGroups
 * @author s_wolff
 */
public class AbstractGroups {

    private AbstractGroups() {
    }

    /**
     * Creates a collection of
     * <code>AbstractGroup</code>s.
     *
     * @param numberOfGroups the number of groups which must be a multiple of 3
     * @return a setting of abstract groups and their assignments
     */
    public static Collection<AbstractGroup> makeAbstractGroups(int numberOfGroups) {
        assert numberOfGroups % 3 == 0;
        return AbstractGroupBuilder.makeAbstractGroups(numberOfGroups);
//        assert numberOfGroups % 3 == 0;
//
//        // throw new UnsupportedOperationException("Not yet implemented.");
//        // testing for 9 groups
//        List<AbstractGroup> groups = new ArrayList<AbstractGroup>(numberOfGroups);
//
//        groups.add(new AbstractGroup(0, 6, 8, AbstractGroup.COURSE_STARTER));
//        groups.add(new AbstractGroup(1, 4, 3, AbstractGroup.COURSE_STARTER));
//        groups.add(new AbstractGroup(2, 5, 7, AbstractGroup.COURSE_STARTER));
//
//        groups.add(new AbstractGroup(4, 0, 7, AbstractGroup.COURSE_MAIN));
//        groups.add(new AbstractGroup(5, 1, 8, AbstractGroup.COURSE_MAIN));
//        groups.add(new AbstractGroup(6, 2, 3, AbstractGroup.COURSE_MAIN));
//
//        groups.add(new AbstractGroup(3, 0, 5, AbstractGroup.COURSE_DESSERT));
//        groups.add(new AbstractGroup(7, 1, 6, AbstractGroup.COURSE_DESSERT));
//        groups.add(new AbstractGroup(8, 2, 4, AbstractGroup.COURSE_DESSERT));
//
//        return groups;
    }

    /**
     * Provides a collection of abstract groups that cook the main course. The
     * retured collection is not backed by the provided collection so changes to
     * the returned collection will not reflect to the provided collection and
     * vice verse. But still the objects both collection are idetically, not
     * equal.
     *
     * @param groups a collection of abstract groups which will be searched for
     * main course chefs
     * @return a collection of all abstract groups that cook a main course
     */
    public static Collection<AbstractGroup> getMainCourseChefs(Collection<AbstractGroup> groups) {
        Collection<AbstractGroup> mainCourseChefs = new ArrayList<AbstractGroup>(groups.size() / 3);
        for (AbstractGroup g : groups) {
            if (g.isMainChef()) {
                mainCourseChefs.add(g);
            }
        }
        return mainCourseChefs;
    }

    /**
     * Searches the abstract group within the provided collection of groups
     * where the group with the provided id will have their main course
     *
     * @param id id of an abstract groups whose main course location is of
     * interest
     * @param groups collection of all groups
     * @return the id of the abstract group that serves the main course for the
     * provided group or -1 if no such group was found
     */
    public static int getMainCourseLocation(int id, Collection<AbstractGroup> groups) {
        for (AbstractGroup g : groups) {
            if (g.isMainChef() && g.hasGuest(id)) {
                return g.getId();
            } else if (g.getId() == id && g.isMainChef()) {
                return id;
            }
        }
        return -1;
    }

    /**
     * Searches the id of the first abstract group that the group with the id provided
     * cooks for
     *
     * @param id ID of AbstractGroup
     * @param groups List of AbstractGroups to be searched in
     * @return ID of first guest group
     */
    public static int getGuest1(int id, Collection<AbstractGroup> groups) {
        for (AbstractGroup g : groups) {
            if (g.getId() == id) {
                return g.getGuest1();
            }
        }
        return -1;
    }

    /**
     * Searches the id of the second abstract group that the group with the id provided
     * cooks for
     *
     * @param id ID of AbstractGroup
     * @param groups List of AbstractGroups to be searched in
     * @return ID of second guest group
     */
    public static int getGuest2(int id, Collection<AbstractGroup> groups) {
        for (AbstractGroup g : groups) {
            if (g.getId() == id) {
                return g.getGuest2();
            }
        }
        return -1;
    }
}
