/*
 * 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.dns;

import static com.google.common.base.Preconditions.checkNotNull;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.api.sensor.Sensor;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceNotUpLogic;
import org.apache.brooklyn.core.location.geo.HostGeoInfo;
import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import org.apache.brooklyn.entity.group.DynamicGroup;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.net.Networking;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;

public abstract class AbstractGeoDnsServiceImpl extends AbstractEntity implements AbstractGeoDnsService {
    private static final Logger log = LoggerFactory.getLogger(AbstractGeoDnsService.class);

    @SetFromFlag
    protected Group targetEntityProvider;
    protected AbstractMembershipTrackingPolicy tracker;
    /** Guards access to {@link #tracker}. */
    protected final Object trackerLock = new Object[0];

    protected Map<Entity, HostGeoInfo> targetHosts = Collections.synchronizedMap(new LinkedHashMap<Entity, HostGeoInfo>());

    // We complain (at debug) when we encounter a target entity for whom we can't derive hostname/ip information; 
    // this is the commonest case for the transient condition between the time the entity is created and the time 
    // it is started (at which point the location is specified). This set contains those entities we've complained 
    // about already, to avoid repetitive logging.
    transient protected Set<Entity> entitiesWithoutHostname = new HashSet<Entity>();

    // We complain (at info/warn) when we encounter a target entity for whom we can't derive geo information, even 
    // when hostname/ip is known. This set contains those entities we've complained about already, to avoid repetitive 
    // logging.
    transient protected Set<Entity> entitiesWithoutGeoInfo = new HashSet<Entity>();

    public AbstractGeoDnsServiceImpl() {
        super();
    }

    @Override
    public void init() {
        super.init();
        Group initialProvider = config().get(ENTITY_PROVIDER);
        if (initialProvider != null) {
            setTargetEntityProvider(initialProvider);
        }
    }

    @Override
    public Map<Entity, HostGeoInfo> getTargetHosts() {
        return targetHosts;
    }

    @Override
    public void onManagementStarted() {
        super.onManagementStarted();
        startTracker();
    }

    @Override
    public void onManagementStopped() {
        endTracker();
        super.onManagementStopped();
    }

    @Override
    public void destroy() {
        setServiceState(Lifecycle.DESTROYED);
        super.destroy();
    }

    @Override
    public void setServiceState(Lifecycle state) {
        sensors().set(HOSTNAME, getHostname());
        ServiceStateLogic.setExpectedState(this, state);
        if (state==Lifecycle.RUNNING)
            ServiceNotUpLogic.clearNotUpIndicator(this, SERVICE_STATE_ACTUAL);
        else
            ServiceNotUpLogic.updateNotUpIndicator(this, SERVICE_STATE_ACTUAL, "Not in RUNNING state");
    }

    @Override
    public void setTargetEntityProvider(final Group entityProvider) {
        this.targetEntityProvider = checkNotNull(entityProvider, "targetEntityProvider");
        startTracker();
    }

    /** should set up so these hosts are targeted, and setServiceState appropriately */
    protected abstract void reconfigureService(Collection<HostGeoInfo> targetHosts);

    /**
     * Start the tracker.
     * <p>
     * Subclasses should take care to synchronize on {@link #trackerLock}.
     */
    protected void startTracker() {
        synchronized (trackerLock) {
            if (targetEntityProvider == null || !getManagementSupport().isDeployed()) {
                log.debug("Tracker for " + this + " not yet active: " + targetEntityProvider + " / " + getManagementContext());
                return;
            }
            endTracker();

            ImmutableSet.Builder<Sensor<?>> sensorsToTrack = ImmutableSet.<Sensor<?>>builder().add(
                    HOSTNAME, ADDRESS, Attributes.MAIN_URI, WebAppService.ROOT_URL);
            // Don't subscribe to lifecycle events if entities will be included regardless of their status.
            if (Boolean.TRUE.equals(config().get(FILTER_FOR_RUNNING))) {
                sensorsToTrack.add(Attributes.SERVICE_STATE_ACTUAL);
            }
            log.debug("Initializing tracker for " + this + ", following " + targetEntityProvider);
            tracker = policies().add(PolicySpec.create(MemberTrackingPolicy.class)
                    .displayName("GeoDNS targets tracker")
                    .configure(AbstractMembershipTrackingPolicy.SENSORS_TO_TRACK, sensorsToTrack.build())
                    .configure(AbstractMembershipTrackingPolicy.GROUP, targetEntityProvider));
            refreshGroupMembership();
        }
    }

    /**
     * End the tracker.
     * <p>
     * Subclasses should take care to synchronize on {@link #trackerLock}.
     */
    protected void endTracker() {
        synchronized (trackerLock) {
            if (tracker == null || targetEntityProvider == null) return;
            policies().remove(tracker);
            tracker = null;
        }
    }

    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
        @Override
        protected void onEntityEvent(EventType type, Entity entity) {
            defaultHighlightAction(type, entity);
            ((AbstractGeoDnsServiceImpl)super.entity).refreshGroupMembership();
        }
    }

    @Override
    public abstract String getHostname();

    long lastUpdate = -1;

    // TODO: remove group member polling once locations can be determined via subscriptions
    protected void refreshGroupMembership() {
        try {
            if (log.isDebugEnabled()) log.debug("GeoDns {} refreshing targets", this);
            if (targetEntityProvider == null)
                return;
            if (targetEntityProvider instanceof DynamicGroup)
                ((DynamicGroup) targetEntityProvider).rescanEntities();
            Set<Entity> pool = MutableSet.copyOf(targetEntityProvider instanceof Group ? targetEntityProvider.getMembers(): targetEntityProvider.getChildren());
            if (log.isDebugEnabled()) log.debug("GeoDns {} refreshing targets, pool now {}", this, pool);

            boolean changed = false;
            boolean filterForRunning = Boolean.TRUE.equals(config().get(FILTER_FOR_RUNNING));
            Set<Entity> previousOnes = MutableSet.copyOf(targetHosts.keySet());
            for (Entity e: pool) {
                if (!filterForRunning || Lifecycle.RUNNING.equals(e.sensors().get(Attributes.SERVICE_STATE_ACTUAL))) {
                    previousOnes.remove(e);
                    changed |= addTargetHost(e);
                }
            }
            // anything left in previousOnes is no longer applicable
            for (Entity e: previousOnes) {
                changed |= removeTargetHost(e, false);
            }

            // do a periodic full update hourly once we are active (the latter is probably not needed)
            if (changed || (lastUpdate > 0 && Time.hasElapsedSince(lastUpdate, Duration.ONE_HOUR))) {
                update();
            }
        } catch (Exception e) {
            log.error("Problem refreshing group membership: "+e, e);
        }
    }

    /**
     * Adds this host, if it is absent or if its hostname has changed.
     * <p>
     * For whether to use hostname or ip, see config and attributes {@link AbstractGeoDnsService#USE_HOSTNAMES}, 
     * {@link Attributes#HOSTNAME} and {@link Attributes#ADDRESS} (via {@link #inferHostname(Entity)} and {@link #inferIp(Entity)}.
     * Note that the "hostname" could in fact be an IP address, if {@link #inferHostname(Entity)} returns an IP!
     * <p>
     * TODO in a future release, we may change this to explicitly set the sensor(s) to look at on the entity, and 
     * be stricter about using them in order.
     * 
     * @return true if host is added or changed
     */
    protected boolean addTargetHost(Entity entity) {
        try {
            HostGeoInfo oldGeo = targetHosts.get(entity);
            String hostname = inferHostname(entity);
            String ip = inferIp(entity);
            String addr = (getConfig(USE_HOSTNAMES) || ip == null) ? hostname : ip;

            if (addr==null) addr = ip;
            if (addr == null) {
                if (entitiesWithoutHostname.add(entity)) {
                    log.debug("GeoDns ignoring {} (no hostname/ip/URL info yet available)", entity);
                }
                return false;
            }

            // prefer the geo from the entity (or location parent), but fall back to inferring
            // e.g. if it supplies a URL
            HostGeoInfo geo = HostGeoInfo.fromEntity(entity);
            if (geo==null) geo = inferHostGeoInfo(hostname, ip);

            if (Networking.isPrivateSubnet(addr) && ip!=null && !Networking.isPrivateSubnet(ip)) {
                // fix for #1216
                log.debug("GeoDns using IP "+ip+" for "+entity+" as addr "+addr+" resolves to private subnet");
                addr = ip;
            }
            if (Networking.isPrivateSubnet(addr)) {
                if (getConfig(INCLUDE_HOMELESS_ENTITIES)) {
                    if (entitiesWithoutGeoInfo.add(entity)) {
                        log.info("GeoDns including {}, even though {} is a private subnet (homeless entities included)", entity, addr);
                    }
                } else {
                    if (entitiesWithoutGeoInfo.add(entity)) {
                        log.warn("GeoDns ignoring {} (private subnet detected for {})", entity, addr);
                    }
                    return false;
                }
            }

            if (geo == null) {
                if (getConfig(INCLUDE_HOMELESS_ENTITIES)) {
                    if (entitiesWithoutGeoInfo.add(entity)) {
                        log.info("GeoDns including {}, even though no geography info available for {})", entity, addr);
                    }
                    geo = HostGeoInfo.create(addr, "unknownLocation("+addr+")", 0, 0);
                } else {
                    if (entitiesWithoutGeoInfo.add(entity)) {
                        log.warn("GeoDns ignoring {} (no geography info available for {})", entity, addr);
                    }
                    return false;
                }
            }

            if (!addr.equals(geo.getAddress())) {
                // if the location provider did not have an address, create a new one with it
                geo = HostGeoInfo.create(addr, geo.displayName, geo.latitude, geo.longitude);
            }

            // If we already knew about it, and it hasn't changed, then nothing to do
            if (oldGeo != null && geo.getAddress().equals(oldGeo.getAddress())) {
                return false;
            }

            entitiesWithoutHostname.remove(entity);
            entitiesWithoutGeoInfo.remove(entity);
            log.info("GeoDns adding "+entity+" at "+geo+(oldGeo != null ? " (previously "+oldGeo+")" : ""));
            targetHosts.put(entity, geo);
            return true;

        } catch (Exception ee) {
            log.warn("GeoDns ignoring "+entity+" (error analysing location): "+ee, ee);
            return false;
        }
    }

    /** remove if host removed */
    protected boolean removeTargetHost(Entity e, boolean doUpdate) {
        if (targetHosts.remove(e) != null) {
            log.info("GeoDns removing reference to {}", e);
            if (doUpdate) update();
            return true;
        }
        return false;
    }

    protected void update() {
        lastUpdate = System.currentTimeMillis();

        Map<Entity, HostGeoInfo> m;
        synchronized(targetHosts) { m = ImmutableMap.copyOf(targetHosts); }
        if (log.isDebugEnabled()) log.debug("Full update of "+this+" ("+m.size()+" target hosts)");

        Map<String,String> entityIdToAddress = Maps.newLinkedHashMap();
        for (Map.Entry<Entity, HostGeoInfo> entry : m.entrySet()) {
            entityIdToAddress.put(entry.getKey().getId(), entry.getValue().address);
        }

        reconfigureService(new LinkedHashSet<HostGeoInfo>(m.values()));

        if (log.isDebugEnabled()) log.debug("Targets being set as "+entityIdToAddress);
        sensors().set(TARGETS, entityIdToAddress);
    }

    protected String inferHostname(Entity entity) {
        String hostname = entity.getAttribute(Attributes.HOSTNAME);
        URI url = entity.getAttribute(Attributes.MAIN_URI);
        if (url!=null) {
            try {
                URL u = url.toURL();

                String hostname2 = u.getHost(); 
                if (hostname==null) {
                    if (!entitiesWithoutGeoInfo.contains(entity))  //don't log repeatedly
                        log.warn("GeoDns "+this+" using URL {} to redirect to {} (HOSTNAME attribute is preferred, but not available)", url, entity);
                    hostname = hostname2;
                } else if (!hostname.equals(hostname2)) {
                    if (!entitiesWithoutGeoInfo.contains(entity))  //don't log repeatedly
                        log.warn("GeoDns "+this+" URL {} of "+entity+" does not match advertised HOSTNAME {}; using hostname, not URL", url, hostname);
                }

                if (u.getPort() > 0 && u.getPort() != 80 && u.getPort() != 443) {
                    if (!entitiesWithoutGeoInfo.contains(entity))  //don't log repeatedly
                        log.warn("GeoDns "+this+" detected non-standard port in URL {} for {}; forwarding may not work", url, entity);
                }

            } catch (MalformedURLException e) {
                log.warn("Invalid URL {} for entity {} in {}", new Object[] {url, entity, this});
            }
        }
        return hostname;
    }

    protected String inferIp(Entity entity) {
        return entity.getAttribute(Attributes.ADDRESS);
    }

    protected HostGeoInfo inferHostGeoInfo(String hostname, String ip) throws UnknownHostException {
        HostGeoInfo geoH = null;
        if (hostname != null) {
            try {
                // For some entities, the hostname can actually be an IP! Therefore use Networking.getInetAddressWithFixedName
                InetAddress addr = Networking.getInetAddressWithFixedName(hostname);
                geoH = HostGeoInfo.fromIpAddress(addr);
            } catch (RuntimeException e) {
                // Most likely caused by (a wrapped) UnknownHostException
                Exceptions.propagateIfFatal(e);
                if (ip == null) {
                    if (log.isTraceEnabled()) log.trace("inferHostGeoInfo failing ("+Exceptions.getFirstInteresting(e)+"): hostname="+hostname+"; ip="+ip);
                    throw e;
                } else {
                    if (log.isTraceEnabled()) log.trace("GeoDns failed to infer GeoInfo from hostname {}; will try with IP {} ({})", new Object[] {hostname, ip, e});
                }
            }
        }

        // Try IP address (prior to Mar 2014 we did not do this if USE_HOSTNAME was set but don't think that is desirable due to #1216)
        if (ip != null) {
            if (geoH == null) {
                InetAddress addr = Networking.getInetAddressWithFixedName(ip);
                geoH = HostGeoInfo.fromIpAddress(addr);
                if (log.isTraceEnabled()) log.trace("GeoDns inferred GeoInfo {} from ip {} (could not infer from hostname {})", new Object[] {geoH, ip, hostname});
            } else {
                geoH = HostGeoInfo.create(ip, geoH.displayName, geoH.latitude, geoH.longitude);
                if (log.isTraceEnabled()) log.trace("GeoDns inferred GeoInfo {} from hostname {}; switching it to ip {}", new Object[] {geoH, hostname, ip});
            }
        } else {
            if (log.isTraceEnabled()) log.trace("GeoDns inferred GeoInfo {} from hostname {}", geoH, hostname);
        }

        return geoH;
    }
}
