/*
 * 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 org.apache.brooklyn.entity.proxy;

import static org.testng.Assert.assertEquals;

import java.io.File;
import java.util.HashSet;

import javax.annotation.Nullable;

import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.proxy.nginx.UrlMapping;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;

import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.io.Files;

public class UrlMappingTest {
    
    private static final Logger log = LoggerFactory.getLogger(UrlMappingTest.class);
    
    private final int initialClusterSize = 2;
    
    private ClassLoader classLoader = getClass().getClassLoader();
    private LocalManagementContext managementContext;
    private File mementoDir;
    
    private TestApplication app;
    private DynamicCluster cluster;
    private UrlMapping urlMapping;
    
    @BeforeMethod(alwaysRun=true)
    public void setup() {
        mementoDir = Files.createTempDir();
        managementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader);

        app = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
        
        EntitySpec<StubAppServer> serverSpec = EntitySpec.create(StubAppServer.class);
        cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
                .configure(DynamicCluster.INITIAL_SIZE, initialClusterSize)
                .configure(DynamicCluster.MEMBER_SPEC, serverSpec));

        urlMapping = app.createAndManageChild(EntitySpec.create(UrlMapping.class)
                .configure("domain", "localhost")
                .configure("target", cluster));

        app.start( ImmutableList.of(
                managementContext.getLocationManager().createLocation(
                        LocationSpec.create(LocalhostMachineProvisioningLocation.class))
                ));
        log.info("app's location managed: "+managementContext.getLocationManager().isManaged(Iterables.getOnlyElement(app.getLocations())));
        log.info("clusters's location managed: "+managementContext.getLocationManager().isManaged(Iterables.getOnlyElement(cluster.getLocations())));
    }

    @AfterMethod(alwaysRun=true)
    public void shutdown() {
        if (app != null) Entities.destroyAll(app.getManagementContext());
        if (mementoDir != null) RebindTestUtils.deleteMementoDir(mementoDir);
    }

    @Test(groups = "Integration")
    public void testTargetMappingsMatchesClusterMembers() {
        // Check updates its TARGET_ADDRESSES (through async subscription)
        assertExpectedTargetsEventually(cluster.getMembers());
    }
    
    @Test(groups = "Integration")
    public void testTargetMappingsRemovesUnmanagedMember() {
        Iterable<StubAppServer> members = Iterables.filter(cluster.getChildren(), StubAppServer.class);
        assertEquals(Iterables.size(members), 2);
        StubAppServer target1 = Iterables.get(members, 0);
        StubAppServer target2 = Iterables.get(members, 1);
        
        // First wait for targets to be listed
        assertExpectedTargetsEventually(members);
        
        // Unmanage one member, and expect the URL Mapping to be updated accordingly
        Entities.unmanage(target1);

        assertExpectedTargetsEventually(ImmutableSet.of(target2));
    }
    
    @Test(groups = "Integration", invocationCount=50)
    public void testTargetMappingsRemovesUnmanagedMemberManyTimes() {
        testTargetMappingsRemovesUnmanagedMember();
    }
    
    @Test(groups = "Integration")
    public void testTargetMappingsRemovesDownMember() {
        Iterable<StubAppServer> members = Iterables.filter(cluster.getChildren(), StubAppServer.class);
        StubAppServer target1 = Iterables.get(members, 0);
        StubAppServer target2 = Iterables.get(members, 1);
        
        // First wait for targets to be listed
        assertExpectedTargetsEventually(members);
        
        // Stop one member, and expect the URL Mapping to be updated accordingly
        target1.sensors().set(StubAppServer.SERVICE_UP, false);

        assertExpectedTargetsEventually(ImmutableSet.of(target2));
    }

    // i think no real reason for other methods to be Integration apart from the time they take;
    // having one in the unit tests is very handy however, and this is a good choice because it does quite a lot!
    @Test
    public void testTargetMappingUpdatesAfterRebind() throws Exception {
        log.info("starting testTargetMappingUpdatesAfterRebind");
        Iterable<StubAppServer> members = Iterables.filter(cluster.getChildren(), StubAppServer.class);
        assertExpectedTargetsEventually(members);
        
        Assert.assertTrue(managementContext.getLocationManager().isManaged(Iterables.getOnlyElement(cluster.getLocations())));
        rebind();
        Assert.assertTrue(managementContext.getLocationManager().isManaged(Iterables.getOnlyElement(cluster.getLocations())),
                "location not managed after rebind");
        
        Iterable<StubAppServer> members2 = Iterables.filter(cluster.getChildren(), StubAppServer.class);
        StubAppServer target1 = Iterables.get(members2, 0);
        StubAppServer target2 = Iterables.get(members2, 1);

        // Expect to have existing targets
        assertExpectedTargetsEventually(ImmutableSet.of(target1, target2));

        // Add a new member; expect member to be added
        log.info("resizing "+cluster+" - "+cluster.getChildren());
        Integer result = cluster.resize(3);
        Assert.assertTrue(managementContext.getLocationManager().isManaged(Iterables.getOnlyElement(cluster.getLocations())));
        log.info("resized "+cluster+" ("+result+") - "+cluster.getChildren());
        HashSet<StubAppServer> newEntities = Sets.newHashSet(Iterables.filter(cluster.getChildren(), StubAppServer.class));
        newEntities.remove(target1);
        newEntities.remove(target2);
        StubAppServer target3 = Iterables.getOnlyElement(newEntities);
        log.info("expecting "+ImmutableSet.of(target1, target2, target3));
        assertExpectedTargetsEventually(ImmutableSet.of(target1, target2, target3));
        
        // Stop one member, and expect the URL Mapping to be updated accordingly
        log.info("pretending one node down");
        target1.sensors().set(StubAppServer.SERVICE_UP, false);
        assertExpectedTargetsEventually(ImmutableSet.of(target2, target3));

        // Unmanage a member, and expect the URL Mapping to be updated accordingly
        log.info("unmanaging another node");
        Entities.unmanage(target2);
        assertExpectedTargetsEventually(ImmutableSet.of(target3));
        log.info("success - testTargetMappingUpdatesAfterRebind");
    }
    
    private void assertExpectedTargetsEventually(final Iterable<? extends Entity> members) {
        Asserts.succeedsEventually(MutableMap.of("timeout", Duration.ONE_MINUTE), new Runnable() {
            public void run() {
                Iterable<String> expectedTargets = Iterables.transform(members, new Function<Entity,String>() {
                        @Override public String apply(@Nullable Entity input) {
                            return input.getAttribute(Attributes.HOSTNAME)+":"+input.getAttribute(Attributes.HTTP_PORT);
                        }});

                assertEquals(ImmutableSet.copyOf(urlMapping.getAttribute(UrlMapping.TARGET_ADDRESSES)), ImmutableSet.copyOf(expectedTargets));
                assertEquals(urlMapping.getAttribute(UrlMapping.TARGET_ADDRESSES).size(), Iterables.size(members));
            }});
    }
    
    private void rebind() throws Exception {
        RebindTestUtils.waitForPersisted(app);
        
        // Stop the old management context, so original nginx won't interfere
        managementContext.terminate();
        
        app = (TestApplication) RebindTestUtils.rebind(mementoDir, getClass().getClassLoader());
        managementContext = (LocalManagementContext) ((EntityInternal)app).getManagementContext();
        cluster = (DynamicCluster) Iterables.find(app.getChildren(), Predicates.instanceOf(DynamicCluster.class));
        urlMapping = (UrlMapping) Iterables.find(app.getChildren(), Predicates.instanceOf(UrlMapping.class));
    }
}
