/*
 * 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.sling.discovery.base.connectors.announcement;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonReaderFactory;
import javax.json.JsonValue;

import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.discovery.ClusterView;
import org.apache.sling.discovery.InstanceDescription;
import org.apache.sling.discovery.commons.providers.DefaultClusterView;
import org.apache.sling.discovery.commons.providers.DefaultInstanceDescription;
import org.apache.sling.discovery.commons.providers.NonLocalInstanceDescription;

/**
 * An announcement is the information exchanged by the topology connector and
 * contains all clusters and instances which both the topology connector client
 * and servlet see (in their part before joining the two worlds).
 * <p>
 * An announcement is exchanged in json format and carries a timeout.
 */
public class Announcement {

    /** the protocol version this announcement currently represents. Mismatching protocol versions are
     * used to detect incompatible topology connectors
     */
    private final static int PROTOCOL_VERSION = 1;

    /** the sling id of the owner of this announcement. the owner is where this announcement comes from **/
    private final String ownerId;

    /** announcement protocol version **/
    private final int protocolVersion;

    /** the local cluster view **/
    private ClusterView localCluster;

    /** the incoming instances **/
    private List<Announcement> incomings = new LinkedList<Announcement>();

    /** whether or not this annoucement was inherited (response of a connect) or incoming (the connect) **/
    private boolean inherited = false;

    /** some information about the server where this announcement came from **/
    private String serverInfo;

    /** whether or not this announcement represents a loop detected in the topology connectors **/
    private boolean loop = false;

    /** SLING-3382: Sets the backoffInterval which the connector servlets passes back to the client to use as the next heartbeatInterval **/
    private long backoffInterval = -1;

    /** SLING-3382: the resetBackoff flag is sent from client to server and indicates that the client wants to start from (backoff) scratch **/
    private boolean resetBackoff = false;
    
    private long originallyCreatedAt = -1;
    
    private long receivedAt = System.currentTimeMillis();
    
    private static final JsonReaderFactory jsonReaderFactory;
    static {
        Map<String, Object> config = new HashMap<String, Object>();
        config.put("org.apache.johnzon.supports-comments", true);
        jsonReaderFactory = Json.createReaderFactory(config);
    }

    public Announcement(final String ownerId) {
        this(ownerId, PROTOCOL_VERSION);
    }

    public Announcement(final String ownerId, int protocolVersion) {
        if (ownerId==null || ownerId.length()==0) {
            throw new IllegalArgumentException("ownerId must not be null or empty");
        }
        this.ownerId = ownerId;
        this.protocolVersion = protocolVersion;
    }

    @Override
    public String toString() {
        StringBuilder incomingList = new StringBuilder();
        for (Iterator<Announcement> it = incomings.iterator(); it.hasNext();) {
            Announcement anIncomingAnnouncement = it.next();
            if (incomingList.length()!=0) {
                incomingList.append(", ");
            }
            incomingList.append(anIncomingAnnouncement);
        }
        return "Announcement[ownerId="+getOwnerId()+
                ", protocolVersion="+protocolVersion+
                ", inherited="+isInherited()+
                ", loop="+loop+
                ", incomings="+incomingList+"]";
    }

    /** check whether this is announcement contains the valid protocol version **/
    public boolean isCorrectVersion() {
        return (protocolVersion==PROTOCOL_VERSION);
    }

    /** check whether this is a valid announcement, containing the minimal information **/
    public boolean isValid() {
        if (ownerId==null || ownerId.length()==0) {
            return false;
        }
        if (loop) {
            return true;
        }
        if (!isCorrectVersion()) {
            return false;
        }
        if (localCluster==null) {
            return false;
        }
        try{
            List<InstanceDescription> instances = localCluster.getInstances();
            if (instances==null || instances.size()==0) {
                return false;
            }
            boolean isOwnerMemberOfLocalCluster = false;
            for (Iterator<InstanceDescription> it = instances.iterator(); it.hasNext();) {
                InstanceDescription instanceDescription = it.next();
                if (instanceDescription.getSlingId().equals(ownerId)) {
                    isOwnerMemberOfLocalCluster = true;
                }
            }
            if (!isOwnerMemberOfLocalCluster) {
                return false;
            }
        } catch(Exception ise) {
            return false;
        }
        return true;
    }

    /** set the inherited flag - if true this means this announcement is the response of a topology connect **/
    public void setInherited(final boolean inherited) {
        this.inherited = inherited;
    }

    /** Returns the inherited flag - if true this means that this announcement is the response of a topology connect **/
    public boolean isInherited() {
        return inherited;
    }

    /** Sets the loop falg - set true when this announcement should represent a loop detected in the topology connectors **/
    public void setLoop(final boolean loop) {
        this.loop = loop;
    }
    
    /** Sets the backoffInterval which the connector servlets passes back to the client to use as the next heartbeatInterval **/
    public void setBackoffInterval(long backoffInterval) {
        this.backoffInterval = backoffInterval;
    }
    
    /** Gets the backoffInterval which the connector servlets passes back to the client to use as the next heartbeatInterval **/
    public long getBackoffInterval() {
        return this.backoffInterval;
    }
    
    public long getOriginallyCreatedAt() {
        return this.originallyCreatedAt;
    }
    
    public long getReceivedAt() {
        return this.receivedAt;
    }
    
    /** sets the resetBackoff flag **/
    public void setResetBackoff(boolean resetBackoff) {
        this.resetBackoff = resetBackoff;
    }
    
    /** gets the resetBackoff flag **/
    public boolean getResetBackoff() {
        return resetBackoff;
    }

    /** Returns the loop flag - set when this announcement represents a loop detected in the topology connectors **/
    public boolean isLoop() {
        return loop;
    }

    /** Returns the protocolVersion of this announcement **/
    public int getProtocolVersion() {
        return protocolVersion;
    }

    /** sets the information about the server where this announcement came from **/
    public void setServerInfo(final String serverInfo) {
        this.serverInfo = serverInfo;
    }

    /** the information about the server where this announcement came from **/
    public String getServerInfo() {
        return serverInfo;
    }

    /**
     * Returns the slingid of the owner of this announcement.
     * <p>
     * The owner is the instance which initiated the topology connection
     */
    public String getOwnerId() {
        return ownerId;
    }
    
    /** Convert this announcement into a json object **/
    private JsonObject asJSONObject(boolean filterTimes) {
        JsonObjectBuilder announcement = Json.createObjectBuilder();
        announcement.add("ownerId", ownerId);
        announcement.add("protocolVersion", protocolVersion);
        // SLING-3389: leaving the 'created' property in the announcement
        // for backwards compatibility!
        if (!filterTimes) {
            announcement.add("created", System.currentTimeMillis());
        }
        announcement.add("inherited", inherited);
        if (loop) {
            announcement.add("loop", loop);
        }
        if (serverInfo != null) {
            announcement.add("serverInfo", serverInfo);
        }
        if (localCluster!=null) {
            announcement.add("localClusterView", asJSON(localCluster));
        }
        if (!filterTimes && backoffInterval>0) {
            announcement.add("backoffInterval", backoffInterval);
        }
        if (resetBackoff) {
            announcement.add("resetBackoff", resetBackoff);
        }
        JsonArrayBuilder incomingAnnouncements = Json.createArrayBuilder();
        for (Iterator<Announcement> it = incomings.iterator(); it.hasNext();) {
            Announcement incoming = it.next();
            incomingAnnouncements.add(incoming.asJSONObject(filterTimes));
        }
        announcement.add("topologyAnnouncements", incomingAnnouncements);
        return announcement.build();
    }

    /** Create an announcement form json **/
    public static Announcement fromJSON(final String topologyAnnouncementJSON) {
        
        JsonObject announcement = jsonReaderFactory.createReader(new StringReader(topologyAnnouncementJSON)).readObject();
        final String ownerId = announcement.getString("ownerId");
        final int protocolVersion;
        if (!announcement.containsKey("protocolVersion")) {
            protocolVersion = -1;
        } else {
            protocolVersion = announcement.getInt("protocolVersion");
        }
        final Announcement result = new Announcement(ownerId, protocolVersion);
        if (announcement.containsKey("created")) {
            result.originallyCreatedAt = announcement.getJsonNumber("created").longValue();
        }
        if (announcement.containsKey("backoffInterval")) {
            long backoffInterval = announcement.getJsonNumber("backoffInterval").longValue();
            result.backoffInterval = backoffInterval;
        }
        if (announcement.containsKey("resetBackoff")) {
            boolean resetBackoff = announcement.getBoolean("resetBackoff");
            result.resetBackoff = resetBackoff;
        }
        if (announcement.containsKey("loop") && announcement.getBoolean("loop")) {
            result.setLoop(true);
            return result;
        }
        if (announcement.containsKey("localClusterView"))
        {
            final String localClusterViewJSON = asJSON(announcement
                    .getJsonObject("localClusterView"));
            
            final ClusterView localClusterView = asClusterView(localClusterViewJSON);
    
            result.setLocalCluster(localClusterView);
        }

        if (announcement.containsKey("inherited")) {
            final Boolean inherited = announcement.getBoolean("inherited");
            result.inherited = inherited;
        }
        if (announcement.containsKey("serverInfo")) {
            String serverInfo = announcement.getString("serverInfo");
            result.serverInfo = serverInfo;
        }

        final JsonArray subAnnouncements = announcement
                .getJsonArray("topologyAnnouncements");
        
        for (int i = 0; i < subAnnouncements.size(); i++) {
            String subAnnouncementJSON = subAnnouncements.getString(i);
            result.addIncomingTopologyAnnouncement(fromJSON(subAnnouncementJSON));
        }
        return result;
    }

    /** create a clusterview from json **/
    private static ClusterView asClusterView(final String localClusterViewJSON) {
        JsonObject obj = jsonReaderFactory.createReader(new StringReader(localClusterViewJSON)).readObject();
        DefaultClusterView clusterView = new DefaultClusterView(
                obj.getString("id"));
        JsonArray instancesObj = obj.getJsonArray("instances");

        for (int i = 0; i < instancesObj.size(); i++) {
            JsonObject anInstance = instancesObj.getJsonObject(i);
            clusterView.addInstanceDescription(asInstance(anInstance));
        }

        return clusterView;
    }

    /** convert a clusterview into json **/
    private static JsonObject asJSON(final ClusterView clusterView) {
        JsonObjectBuilder obj = Json.createObjectBuilder();
        obj.add("id", clusterView.getId());
        JsonArrayBuilder instancesObj = Json.createArrayBuilder();
        List<InstanceDescription> instances = clusterView.getInstances();
        for (Iterator<InstanceDescription> it = instances.iterator(); it
                .hasNext();) {
            InstanceDescription instanceDescription = it.next();
            instancesObj.add(asJSON(instanceDescription));
        }
        obj.add("instances", instancesObj);
        return obj.build();
    }

    /** create an instancedescription from json **/
    private static DefaultInstanceDescription asInstance(final JsonObject anInstance) {
        final boolean isLeader = anInstance.getBoolean("isLeader");
        final String slingId = anInstance.getString("slingId");

        final JsonObject propertiesObj = anInstance.getJsonObject("properties");
        Iterator<String> it = propertiesObj.keySet().iterator();
        Map<String, String> properties = new HashMap<String, String>();
        while (it.hasNext()) {
            String key = it.next();
            properties.put(key, propertiesObj.getString(key));
        }

        NonLocalInstanceDescription instance = new NonLocalInstanceDescription(
                null, isLeader, slingId, properties);
        return instance;
    }

    /** convert an instance description into a json object **/
    private static JsonObject asJSON(final InstanceDescription instanceDescription) {
        JsonObjectBuilder obj = Json.createObjectBuilder();
        obj.add("slingId", instanceDescription.getSlingId());
        obj.add("isLeader", instanceDescription.isLeader());
        ClusterView cluster = instanceDescription.getClusterView();
        if (cluster != null) {
            obj.add("cluster", cluster.getId());
        }
        JsonObjectBuilder propertiesObj = Json.createObjectBuilder();
        Map<String, String> propertiesMap = instanceDescription.getProperties();
        for (Iterator<Entry<String, String>> it = propertiesMap.entrySet()
                .iterator(); it.hasNext();) {
            Entry<String, String> entry = it.next();
            propertiesObj.add(entry.getKey(), entry.getValue());
        }
        obj.add("properties", propertiesObj);
        return obj.build();
    }

    /** sets the local clusterview **/
    public void setLocalCluster(ClusterView localCluster) {
        this.localCluster = localCluster;
    }

    /** adds an incoming announcement to this announcement **/
    public void addIncomingTopologyAnnouncement(
            Announcement incomingTopologyAnnouncement) {
        incomings.add(incomingTopologyAnnouncement);
    }

    /** Convert this announcement into json **/
    public String asJSON() {
        return asJSON(asJSONObject(false));
    }
    
    private static String asJSON(JsonValue json) {
        StringWriter writer = new StringWriter();
        Json.createGenerator(writer).write(json).close();
        return writer.toString();
    }

    /** the key which is unique to this announcement **/
    public String getPrimaryKey() {
        return ownerId;
    }

    /** Returns the list of instances that are contained in this announcement **/
    public Collection<InstanceDescription> listInstances() {
        Collection<InstanceDescription> instances = new LinkedList<InstanceDescription>();
        instances.addAll(localCluster.getInstances());

        for (Iterator<Announcement> it = incomings.iterator(); it.hasNext();) {
            Announcement incomingAnnouncement = it.next();
            instances.addAll(incomingAnnouncement.listInstances());
        }
        return instances;
    }

    /**
     * Persists this announcement using the given 'announcements' resource,
     * under which a node with the primary key is created
     **/
    public void persistTo(Resource announcementsResource)
            throws PersistenceException {
        Resource announcementChildResource = announcementsResource.getChild(getPrimaryKey());
        
        // SLING-2967 used to introduce 'resetting the created time' here
        // in order to become machine-clock independent.
        // With introduction of SLING-3389, where we dont store any
        // announcement-heartbeat-dates anymore at all, this resetting here
        // became unnecessary.
        
        final String announcementJson = asJSON();
		if (announcementChildResource==null) {
            final ResourceResolver resourceResolver = announcementsResource.getResourceResolver();
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put("topologyAnnouncement", announcementJson);
            resourceResolver.create(announcementsResource, getPrimaryKey(), properties);
        } else {
            final ModifiableValueMap announcementChildMap = announcementChildResource.adaptTo(ModifiableValueMap.class);
            announcementChildMap.put("topologyAnnouncement", announcementJson);
        }
    }

	/**
     * Remove all announcements that match the given owner Id
     */
    public void removeInherited(final String ownerId) {
        for (Iterator<Announcement> it = incomings.iterator(); it.hasNext();) {
            Announcement anIncomingAnnouncement = it.next();
            if (anIncomingAnnouncement.isInherited()
                    && anIncomingAnnouncement.getOwnerId().equals(ownerId)) {
                // then filter this
                it.remove();
            }

        }
    }

    /**
     * Compare this Announcement with another one, ignoring the 'created'
     * property - which gets added to the JSON object automatically due
     * to SLING-3389 wire-backwards-compatibility - and backoffInterval
     * introduced as part of SLING-3382
     */
    public boolean correspondsTo(Announcement announcement) {
        final JsonObject myJson = asJSONObject(true);
        final JsonObject otherJson = announcement.asJSONObject(true);
        return asJSON(myJson).equals(asJSON(otherJson));
    }

    public void registerPing(Announcement incomingAnnouncement) {
        originallyCreatedAt = incomingAnnouncement.originallyCreatedAt;
        receivedAt = incomingAnnouncement.receivedAt;
    }

}
