/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 brooklyn.entity.group;

import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;

import java.util.List;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.EmptySoftwareProcess;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.location.Location;
import brooklyn.location.LocationSpec;
import brooklyn.location.MachineLocation;
import brooklyn.location.MachineProvisioningLocation;
import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import brooklyn.location.basic.MultiLocation;
import brooklyn.test.Asserts;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * Uses {@link SoftwareProcess}, so test can't be in core project.
 * 
 * Different from {@link DynamicClusterWithAvailabilityZonesTest} in the use of {@link MultiLocation}.
 * However, the difference is important: the {@link SoftwareProcess} entity has two locations
 * (the {@link MachineProvisioningLocation} and the {@link MachineLocation}, which was previously
 * causing a failure - now fixed and tested here.
 */
public class DynamicClusterWithAvailabilityZonesMultiLocationTest extends BrooklynAppUnitTestSupport {
    
    private DynamicCluster cluster;
    
    private LocalhostMachineProvisioningLocation subLoc1;
    private LocalhostMachineProvisioningLocation subLoc2;
    private MultiLocation<?> multiLoc;
    
    @BeforeMethod(alwaysRun=true)
    @Override
    public void setUp() throws Exception {
        super.setUp();
        cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
                .configure(DynamicCluster.ENABLE_AVAILABILITY_ZONES, true)
                .configure(DynamicCluster.INITIAL_SIZE, 0)
                .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(EmptySoftwareProcess.class)));
        
        subLoc1 = app.newLocalhostProvisioningLocation(ImmutableMap.of("displayName", "loc1"));
        subLoc2 = app.newLocalhostProvisioningLocation(ImmutableMap.of("displayName", "loc2"));
        multiLoc = mgmt.getLocationManager().createLocation(LocationSpec.create(MultiLocation.class)
                .configure(MultiLocation.SUB_LOCATIONS, ImmutableList.<MachineProvisioningLocation<?>>of(subLoc1, subLoc2)));
    }

    @Test
    public void testReplacesEntityInSameZone() throws Exception {
        ((EntityLocal)cluster).config().set(DynamicCluster.ENABLE_AVAILABILITY_ZONES, true);
        cluster.start(ImmutableList.of(multiLoc));
        
        cluster.resize(4);
        List<String> locsUsed = getLocationNames(getLocationsOf(cluster.getMembers(), Predicates.instanceOf(MachineProvisioningLocation.class)));
        Asserts.assertEqualsIgnoringOrder(locsUsed, ImmutableList.of("loc1", "loc1", "loc2", "loc2"));

        String idToRemove = Iterables.getFirst(cluster.getMembers(), null).getId();
        String idAdded = cluster.replaceMember(idToRemove);
        locsUsed = getLocationNames(getLocationsOf(cluster.getMembers(), Predicates.instanceOf(MachineProvisioningLocation.class)));
        Asserts.assertEqualsIgnoringOrder(locsUsed, ImmutableList.of("loc1", "loc1", "loc2", "loc2"));
        assertNull(Iterables.find(cluster.getMembers(), EntityPredicates.idEqualTo(idToRemove), null));
        assertNotNull(Iterables.find(cluster.getMembers(), EntityPredicates.idEqualTo(idAdded), null));
    }
    
    protected List<Location> getLocationsOf(Iterable<? extends Entity> entities, Predicate<? super Location> filter) {
        List<Location> result = Lists.newArrayList();
        for (Entity entity : entities) {
            Iterables.addAll(result, Iterables.filter(entity.getLocations(), filter));
        }
        return result;
    }

    protected List<String> getLocationNames(Iterable<? extends Location> locs) {
        List<String> result = Lists.newArrayList();
        for (Location subLoc : locs) {
            result.add(subLoc.getDisplayName());
        }
        return result;
    }
}
