/*
 * 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.  TcSee the License for the 
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.stratos.autoscaler.client;

import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.autoscaler.applications.pojo.ApplicationClusterContext;
import org.apache.stratos.autoscaler.applications.pojo.VolumeContext;
import org.apache.stratos.autoscaler.exception.cartridge.SpawningException;
import org.apache.stratos.autoscaler.util.AutoscalerConstants;
import org.apache.stratos.autoscaler.util.AutoscalerObjectConverter;
import org.apache.stratos.autoscaler.util.AutoscalerUtil;
import org.apache.stratos.autoscaler.util.ConfUtil;
import org.apache.stratos.cloud.controller.stub.*;
import org.apache.stratos.cloud.controller.stub.domain.InstanceContext;
import org.apache.stratos.cloud.controller.stub.domain.MemberContext;
import org.apache.stratos.cloud.controller.stub.domain.Volume;
import org.apache.stratos.common.Properties;
import org.apache.stratos.common.Property;
import org.apache.stratos.common.constants.StratosConstants;
import org.apache.stratos.common.partition.PartitionRef;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

/**
 * This class will call cloud controller web service to take the action decided by Autoscaler
 */
public class AutoscalerCloudControllerClient {
    private static final Log log = LogFactory.getLog(AutoscalerCloudControllerClient.class);
    private static final String AS_CC_CLIENT_MAX_CONNECTIONS_PER_HOST_KEY =
            "autoscaler.cloud.controller.client.max.connections.per.host";
    private static final String AS_CC_CLIENT_MAX_TOTAL_CONNECTIONS_KEY =
            "autoscaler.cloud.controller.client.max.total.connections";
    private static final int AS_CC_CLIENT_MAX_CONNECTIONS_PER_HOST = Integer.getInteger
            (AS_CC_CLIENT_MAX_CONNECTIONS_PER_HOST_KEY, 25);
    private static final int AS_CC_CLIENT_MAX_TOTAL_CONNECTIONS = Integer.getInteger
            (AS_CC_CLIENT_MAX_TOTAL_CONNECTIONS_KEY, 30);
    private static CloudControllerServiceStub stub;

    private AutoscalerCloudControllerClient() {
        MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager = new
                MultiThreadedHttpConnectionManager();
        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
        params.setDefaultMaxConnectionsPerHost(AS_CC_CLIENT_MAX_CONNECTIONS_PER_HOST);
        params.setMaxTotalConnections(AS_CC_CLIENT_MAX_TOTAL_CONNECTIONS);
        multiThreadedHttpConnectionManager.setParams(params);
        HttpClient httpClient = new HttpClient(multiThreadedHttpConnectionManager);

        try {
            ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
            ctx.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
            XMLConfiguration conf = ConfUtil.getInstance(null).getConfiguration();
            int port = conf.getInt("autoscaler.cloudController.port", AutoscalerConstants
                    .CLOUD_CONTROLLER_DEFAULT_PORT);
            String hostname = conf.getString("autoscaler.cloudController.hostname", "localhost");
            String epr = "https://" + hostname + ":" + port + "/" + AutoscalerConstants.CLOUD_CONTROLLER_SERVICE_SFX;
            int cloudControllerClientTimeout = conf.getInt("autoscaler.cloudController.clientTimeout", 180000);

            stub = new CloudControllerServiceStub(ctx, epr);
            stub._getServiceClient().getOptions().setProperty(HTTPConstants.SO_TIMEOUT, cloudControllerClientTimeout);
            stub._getServiceClient().getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT,
                    cloudControllerClientTimeout);
            stub._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED, Constants.VALUE_FALSE);
            stub._getServiceClient().getOptions().setProperty(Constants.Configuration.DISABLE_SOAP_ACTION, Boolean
                    .TRUE);
        } catch (Exception e) {
            log.error("Could not initialize cloud controller client", e);
        }
    }

    public static AutoscalerCloudControllerClient getInstance() {
        return InstanceHolder.INSTANCE;
    }

    public synchronized MemberContext startInstance(PartitionRef partition,
                                                    String clusterId, String clusterInstanceId,
                                                    String networkPartitionId, int minMemberCount,
                                                    String scalingDecisionId) throws SpawningException {
        try {
            if (log.isInfoEnabled()) {
                log.info(String.format("Trying to spawn an instance via cloud controller: " +
                                "[cluster] %s [partition] %s [network-partition-id] %s",
                        clusterId, partition.getId(), networkPartitionId));
            }

            XMLConfiguration conf = ConfUtil.getInstance(null).getConfiguration();
            long expiryTime = conf.getLong(StratosConstants.OBSOLETED_MEMBER_EXPIRY_TIMEOUT, 86400000);
            if (log.isDebugEnabled()) {
                log.debug("Member obsolete expiry time is set to: " + expiryTime);
            }

            InstanceContext instanceContext = new InstanceContext();
            instanceContext.setClusterId(clusterId);
            instanceContext.setClusterInstanceId(clusterInstanceId);
            instanceContext.setPartition(AutoscalerObjectConverter.convertPartitionToCCPartition(partition));
            instanceContext.setInitTime(System.currentTimeMillis());
            instanceContext.setObsoleteExpiryTime(expiryTime);
            instanceContext.setNetworkPartitionId(networkPartitionId);

            Properties memberContextProps = new Properties();
            Property minCountProp = new Property();
            minCountProp.setName(StratosConstants.MIN_COUNT);
            minCountProp.setValue(String.valueOf(minMemberCount));
            memberContextProps.addProperty(minCountProp);
            Property scalingDecisionIdProp = new Property();
            scalingDecisionIdProp.setName(StratosConstants.SCALING_DECISION_ID);
            scalingDecisionIdProp.setValue(String.valueOf(scalingDecisionId));
            memberContextProps.addProperty(scalingDecisionIdProp);
            instanceContext.setProperties(AutoscalerUtil.toStubProperties(memberContextProps));

            long startTime = System.currentTimeMillis();
            MemberContext memberContext = stub.startInstance(instanceContext);

            if (log.isDebugEnabled()) {
                long endTime = System.currentTimeMillis();
                log.debug(String.format("Service call startInstance() returned in %dms", (endTime - startTime)));
            }
            return memberContext;
        } catch (CloudControllerServiceCartridgeNotFoundExceptionException e) {
            String message = e.getFaultMessage().getCartridgeNotFoundException().getMessage();
            log.error(message, e);
            throw new SpawningException(message, e);
        } catch (RemoteException e) {
            log.error(e.getMessage(), e);
            throw new SpawningException(e.getMessage(), e);
        } catch (CloudControllerServiceInvalidIaasProviderExceptionException e) {
            String message = e.getFaultMessage().getInvalidIaasProviderException().getMessage();
            log.error(message, e);
            throw new SpawningException(message, e);
        } catch (CloudControllerServiceCloudControllerExceptionException e) {
            String message = e.getMessage();
            log.error(message, e);
            throw new SpawningException(message, e);
        }
    }

    public synchronized void createApplicationClusters(String appId,
                                                       ApplicationClusterContext[] applicationClusterContexts) {
        List<org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext> contextDTOs =
                new ArrayList<org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext>();
        if (applicationClusterContexts != null) {
            for (ApplicationClusterContext applicationClusterContext : applicationClusterContexts) {
                if (applicationClusterContext != null) {
                    org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext dto =
                            new org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext();
                    dto.setClusterId(applicationClusterContext.getClusterId());
                    dto.setAutoscalePolicyName(applicationClusterContext.getAutoscalePolicyName());
                    dto.setDeploymentPolicyName(applicationClusterContext.getDeploymentPolicyName());
                    dto.setCartridgeType(applicationClusterContext.getCartridgeType());
                    dto.setHostName(applicationClusterContext.getHostName());
                    dto.setTenantRange(applicationClusterContext.getTenantRange());
                    dto.setTextPayload(applicationClusterContext.getTextPayload());
                    dto.setProperties(AutoscalerUtil.toStubProperties(applicationClusterContext.getProperties()));
                    dto.setDependencyClusterIds(applicationClusterContext.getDependencyClusterIds());
                    if (applicationClusterContext.getPersistenceContext() != null) {
                        dto.setVolumeRequired(true);
                        dto.setVolumes(convertVolumesToStubVolumes(
                                applicationClusterContext.getPersistenceContext().getVolumes()));
                    }
                    contextDTOs.add(dto);
                }
            }
        }

        org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext[] applicationClusterContextDTOs =
                new org.apache.stratos.cloud.controller.stub.domain.ApplicationClusterContext[contextDTOs.size()];
        contextDTOs.toArray(applicationClusterContextDTOs);
        try {
            stub.createApplicationClusters(appId, applicationClusterContextDTOs);
        } catch (RemoteException e) {
            String msg = e.getMessage();
            log.error(msg, e);
        } catch (CloudControllerServiceApplicationClusterRegistrationExceptionException e) {
            String msg = e.getMessage();
            log.error(msg, e);
        }
    }

    private Volume[] convertVolumesToStubVolumes(VolumeContext[] volumeContexts) {

        ArrayList<Volume> volumes = new ArrayList<Volume>();
        for (VolumeContext volumeContext : volumeContexts) {
            Volume volume = new Volume();
            volume.setRemoveOntermination(volumeContext.isRemoveOntermination());
            volume.setMappingPath(volumeContext.getMappingPath());
            volume.setId(volumeContext.getId());
            volume.setDevice(volumeContext.getDevice());
            volume.setIaasType(volumeContext.getIaasType());
            volume.setSnapshotId(volumeContext.getSnapshotId());
            volume.setVolumeId(volumeContext.getVolumeId());
            volume.setSize(volumeContext.getSize());
            volumes.add(volume);
        }
        return volumes.toArray(new Volume[volumes.size()]);
    }

    public void terminateInstance(String memberId) throws Exception {
        if (log.isInfoEnabled()) {
            log.info(String.format("Terminating instance via cloud controller: [member] %s", memberId));
        }
        long startTime = System.currentTimeMillis();
        stub.terminateInstance(memberId);
        if (log.isDebugEnabled()) {
            long endTime = System.currentTimeMillis();
            log.debug(String.format("Service call terminateInstance() returned in %dms", (endTime - startTime)));
        }
    }

    public void terminateInstanceForcefully(String memberId) throws Exception {
        if (log.isDebugEnabled()) {
            log.debug(String.format("Terminating instance forcefully via cloud controller: [member] %s", memberId));
        }
        stub.terminateInstanceForcefully(memberId);
    }

    public void terminateAllInstances(String clusterId) throws RemoteException,
            CloudControllerServiceInvalidClusterExceptionException {
        if (log.isInfoEnabled()) {
            log.info(String.format("Terminating all instances of cluster via cloud controller: [cluster] %s",
                    clusterId));
        }
        long startTime = System.currentTimeMillis();
        stub.terminateInstances(clusterId);

        if (log.isDebugEnabled()) {
            long endTime = System.currentTimeMillis();
            log.debug(String.format("Service call terminateInstances() returned in %dms", (endTime - startTime)));
        }
    }

    /* An instance of a CloudControllerClient is created when the class is loaded.
     * Since the class is loaded only once, it is guaranteed that an object of
     * CloudControllerClient is created only once. Hence it is singleton.
     */
    private static class InstanceHolder {
        private static final AutoscalerCloudControllerClient INSTANCE = new AutoscalerCloudControllerClient();
    }
}
