/*
 * 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.axis2.clustering.context;

import org.apache.axis2.clustering.ClusteringFault;
import org.apache.axis2.clustering.context.commands.ContextClusteringCommandCollection;
import org.apache.axis2.clustering.context.commands.DeleteServiceGroupContextCommand;
import org.apache.axis2.clustering.context.commands.UpdateConfigurationContextCommand;
import org.apache.axis2.clustering.context.commands.UpdateContextCommand;
import org.apache.axis2.clustering.context.commands.UpdateServiceContextCommand;
import org.apache.axis2.clustering.context.commands.UpdateServiceGroupContextCommand;
import org.apache.axis2.context.AbstractContext;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.PropertyDifference;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.ServiceGroupContext;
import org.apache.axis2.deployment.DeploymentConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 */
public final class ContextClusteringCommandFactory {

    private static final Log log = LogFactory.getLog(ContextClusteringCommandFactory.class);

    public static ContextClusteringCommandCollection
    getCommandCollection(AbstractContext[] contexts,
                         Map excludedReplicationPatterns) {

        ArrayList<ContextClusteringCommand> commands = new ArrayList<ContextClusteringCommand>(contexts.length);
        ContextClusteringCommandCollection collection =
                new ContextClusteringCommandCollection(commands);
        for (AbstractContext context : contexts) {
            ContextClusteringCommand cmd = getUpdateCommand(context,
                                                            excludedReplicationPatterns,
                                                            false);
            if (cmd != null) {
                commands.add(cmd);
            }
        }
        return collection;
    }

    /**
     * @param context                  The context
     * @param excludedPropertyPatterns The property patterns to be excluded
     * @param includeAllProperties     True - Include all properties,
     *                                 False - Include only property differences
     * @return ContextClusteringCommand
     */
    public static ContextClusteringCommand getUpdateCommand(AbstractContext context,
                                                            Map excludedPropertyPatterns,
                                                            boolean includeAllProperties) {

        UpdateContextCommand cmd = toUpdateContextCommand(context);
        if (cmd != null) {
            fillProperties(cmd,
                           context,
                           excludedPropertyPatterns,
                           includeAllProperties);
            if (cmd.isPropertiesEmpty()) {
                cmd = null;
            }
        }
        return cmd;
    }


    public static ContextClusteringCommand getUpdateCommand(AbstractContext context,
                                                            String[] propertyNames)
            throws ClusteringFault {

        UpdateContextCommand cmd = toUpdateContextCommand(context);
        if (cmd != null) {
            fillProperties(cmd, context, propertyNames);
            if (cmd.isPropertiesEmpty()) {
                cmd = null;
            }
        }
        return cmd;
    }

    private static UpdateContextCommand toUpdateContextCommand(AbstractContext context) {
        UpdateContextCommand cmd = null;
        if (context instanceof ConfigurationContext) {
            cmd = new UpdateConfigurationContextCommand();
        } else if (context instanceof ServiceGroupContext) {
            ServiceGroupContext sgCtx = (ServiceGroupContext) context;
            cmd = new UpdateServiceGroupContextCommand();
            UpdateServiceGroupContextCommand updateSgCmd = (UpdateServiceGroupContextCommand) cmd;
            updateSgCmd.setServiceGroupName(sgCtx.getDescription().getServiceGroupName());
            updateSgCmd.setServiceGroupContextId(sgCtx.getId());
        } else if (context instanceof ServiceContext) {
            ServiceContext serviceCtx = (ServiceContext) context;
            cmd = new UpdateServiceContextCommand();
            UpdateServiceContextCommand updateServiceCmd = (UpdateServiceContextCommand) cmd;
            String sgName =
                    serviceCtx.getServiceGroupContext().getDescription().getServiceGroupName();
            updateServiceCmd.setServiceGroupName(sgName);
            updateServiceCmd.setServiceGroupContextId(serviceCtx.getServiceGroupContext().getId());
            updateServiceCmd.setServiceName(serviceCtx.getAxisService().getName());
        }
        return cmd;
    }

    /**
     * @param updateCmd                The command
     * @param context                  The context
     * @param excludedPropertyPatterns The property patterns to be excluded from replication
     * @param includeAllProperties     True - Include all properties,
     *                                 False - Include only property differences
     */
    private static void fillProperties(UpdateContextCommand updateCmd,
                                       AbstractContext context,
                                       Map excludedPropertyPatterns,
                                       boolean includeAllProperties) {
        if (!includeAllProperties) {
            synchronized (context) {
                Map diffs = context.getPropertyDifferences();
                for (Object o : diffs.keySet()) {
                    String key = (String) o;
                    PropertyDifference diff = (PropertyDifference) diffs.get(key);
                    Object value = diff.getValue();

                    if (value instanceof Serializable) {

                        // Next check whether it matches an excluded pattern
                        if (!isExcluded(key,
                                        context.getClass().getName(),
                                        excludedPropertyPatterns)) {
                            if (log.isDebugEnabled()) {
                                log.debug("sending property =" + key + "-" + value);
                            }
                            updateCmd.addProperty(diff);
                        }
                    }
                }
            }
        } else {
            synchronized (context) {
                for (Iterator iter = context.getPropertyNames(); iter.hasNext();) {
                    String key = (String) iter.next();
                    Object value = context.getPropertyNonReplicable(key);
                    if (value instanceof Serializable) {

                        // Next check whether it matches an excluded pattern
                        if (!isExcluded(key, context.getClass().getName(), excludedPropertyPatterns)) {
                            if (log.isDebugEnabled()) {
                                log.debug("sending property =" + key + "-" + value);
                            }
                            PropertyDifference diff = new PropertyDifference(key, value, false);
                            updateCmd.addProperty(diff);
                        }
                    }
                }
            }
        }
    }

    private static void fillProperties(UpdateContextCommand updateCmd,
                                       AbstractContext context,
                                       String[] propertyNames) throws ClusteringFault {
        Map diffs = context.getPropertyDifferences();
        for (String key : propertyNames) {
            Object prop = context.getPropertyNonReplicable(key);

            // First check whether it is serializable
            if (prop instanceof Serializable) {
                if (log.isDebugEnabled()) {
                    log.debug("sending property =" + key + "-" + prop);
                }
                PropertyDifference diff = (PropertyDifference) diffs.get(key);
                if (diff != null) {
                    diff.setValue(prop);
                    updateCmd.addProperty(diff);

                    // Remove the diff?
                    diffs.remove(key);
                }
            } else {
                String msg =
                        "Trying to replicate non-serializable property " + key +
                        " in context " + context;
                throw new ClusteringFault(msg);
            }
        }
    }

    private static boolean isExcluded(String propertyName,
                                      String ctxClassName,
                                      Map excludedPropertyPatterns) {

        // Check in the excludes list specific to the context
        List specificExcludes =
                (List) excludedPropertyPatterns.get(ctxClassName);
        boolean isExcluded = false;
        if (specificExcludes != null) {
            isExcluded = isExcluded(specificExcludes, propertyName);
        }
        if (!isExcluded) {
            // check in the default excludes
            List defaultExcludes =
                    (List) excludedPropertyPatterns.get(DeploymentConstants.TAG_DEFAULTS);
            if (defaultExcludes != null) {
                isExcluded = isExcluded(defaultExcludes, propertyName);
            }
        }
        return isExcluded;
    }

    private static boolean isExcluded(List list, String propertyName) {
        for (Object aList : list) {
            String pattern = (String) aList;
            if (pattern.startsWith("*")) {
                pattern = pattern.replaceAll("\\*", "");
                if (propertyName.endsWith(pattern)) {
                    return true;
                }
            } else if (pattern.endsWith("*")) {
                pattern = pattern.replaceAll("\\*", "");
                if (propertyName.startsWith(pattern)) {
                    return true;
                }
            } else if (pattern.equals(propertyName)) {
                return true;
            }
        }
        return false;
    }

    public static ContextClusteringCommand getRemoveCommand(AbstractContext abstractContext) {
        if (abstractContext instanceof ServiceGroupContext) {
            ServiceGroupContext sgCtx = (ServiceGroupContext) abstractContext;
            DeleteServiceGroupContextCommand cmd = new DeleteServiceGroupContextCommand();
            cmd.setServiceGroupContextId(sgCtx.getId());

            return cmd;
        }
        return null;
    }
}
