/*
 * 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.stratos.autoscaler.applications.topic;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.autoscaler.AutoscalerContext;
import org.apache.stratos.autoscaler.applications.ApplicationHolder;
import org.apache.stratos.autoscaler.applications.pojo.ApplicationClusterContext;
import org.apache.stratos.autoscaler.client.cloud.controller.CloudControllerClient;
import org.apache.stratos.autoscaler.exception.DependencyBuilderException;
import org.apache.stratos.autoscaler.exception.TopologyInConsistentException;
import org.apache.stratos.autoscaler.grouping.topic.ClusterStatusEventPublisher;
import org.apache.stratos.autoscaler.monitor.ApplicationMonitorFactory;
import org.apache.stratos.autoscaler.monitor.application.ApplicationMonitor;
import org.apache.stratos.autoscaler.monitor.group.GroupMonitor;
import org.apache.stratos.messaging.domain.applications.*;
import org.apache.stratos.messaging.domain.topology.Topology;
import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;

import java.util.Collection;
import java.util.Set;

/**
 * This will build the application.
 */
public class ApplicationBuilder {
    private static final Log log = LogFactory.getLog(ApplicationBuilder.class);


    /*public static synchronized void handleApplicationDeployed(Application application,
                                                              Set<ApplicationClusterContext> applicationClusterContexts,
                                                              Set<MetaDataHolder> metaDataHolders) {


        Applications applications = Appcation.getApplications();
        try {
            ApplicationHolder.acquireWriteLock();

            if (applications.applicationExists(application.getUniqueIdentifier())) {
                log.warn("Application with id [ " + application.getUniqueIdentifier() + " ] already exists in Applications");
                return;
            }
            List<Cluster> clusters = new ArrayList<Cluster>();
            for (ApplicationClusterContext applicationClusterContext : applicationClusterContexts) {
                Cluster cluster = new Cluster(applicationClusterContext.getCartridgeType(),
                        applicationClusterContext.getClusterId(), applicationClusterContext.getDeploymentPolicyName(),
                        applicationClusterContext.getAutoscalePolicyName(), application.getUniqueIdentifier());
                //cluster.setStatus(Status.Created);
                cluster.addHostName(applicationClusterContext.getHostName());
                cluster.setTenantRange(applicationClusterContext.getTenantRange());
                clusters.add(cluster);

                Service service = applications.getService(applicationClusterContext.getCartridgeType());
                if (service != null) {
                    service.addCluster(cluster);
                    log.info("Added Cluster " + cluster.toString() + " to Applications for Application with id: " + application.getUniqueIdentifier());
                } else {
                    log.error("Service " + applicationClusterContext.getCartridgeType() + " not found");
                    return;
                }
            }

            // add to Applications and update
            applications.addApplication(application);
            ApplicationHolder.persistApplication(applications);

            log.info("Application with id [ " + application.getUniqueIdentifier() + " ] added to Applications successfully");
            org.apache.stratos.messaging.event.applications.ApplicationCreatedEvent applicationCreatedEvent = new org.apache.stratos.messaging.event.applications.ApplicationCreatedEvent(application, clusters);
            ApplicationsEventPublisher.sendApplicationCreatedEvent(applicationCreatedEvent);

        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }*/

    /*public static synchronized void handleApplicationUndeployed(String applicationId) {

        Set<ClusterDataHolder> clusterData;

        // update the Application and Cluster Statuses as 'Terminating'
        ApplicationHolder.acquireWriteLock();

        try {

            Applications applications = ApplicationHolder.getApplications();

            if (!applications.applicationExists(applicationId)) {
                log.warn("Application with id [ " + applicationId + " ] doesn't exist in Applications");
                return;
            }

            Application application = applications.getApplication(applicationId);
            // check and update application status to 'Terminating'
            if (!application.isStateTransitionValid(ApplicationStatus.Terminating)) {
                log.error("Invalid state transfer from " + application.getStatus() + " to " + ApplicationStatus.Terminating);
            }
            // for now anyway update the status forcefully
            application.setStatus(ApplicationStatus.Terminating);

            // update all the Clusters' statuses to 'Terminating'
            clusterData = application.getClusterDataRecursively();
            for (ClusterDataHolder clusterDataHolder : clusterData) {
                Service service = applications.getService(clusterDataHolder.getServiceType());
                if (service != null) {
                    Cluster aCluster = service.getCluster(clusterDataHolder.getClusterId());
                    if (aCluster != null) {
                        // validate state transition
                        if (!aCluster.isStateTransitionValid(ClusterStatus.Terminating)) {
                            log.error("Invalid state transfer from " + aCluster.getStatus() + " to "
                                    + ClusterStatus.Terminating);
                        }
                        // for now anyway update the status forcefully
                        aCluster.setStatus(ClusterStatus.Terminating);

                    } else {
                        log.warn("Unable to find Cluster with cluster id " + clusterDataHolder.getClusterId() +
                                " in Applications");
                    }

                } else {
                    log.warn("Unable to remove cluster with cluster id: " + clusterDataHolder.getClusterId() + " from Applications, " +
                            " associated Service [ " + clusterDataHolder.getServiceType() + " ] not found");
                }
            }

            // update all Group's statuses to 'Terminating'
            if (application.getGroups() != null) {
                updateGroupStatusesRecursively(GroupStatus.Terminating, application.getGroups());
            }

            ApplicationHolder.persistApplication(applications);

        } finally {
            ApplicationHolder.releaseWriteLock();
        }

        ApplicationsEventPublisher.sendApplicationUndeployedEvent(applicationId, clusterData);
    }*/

    public static synchronized void handleCompleteApplication (Applications applications) {
        if(log.isDebugEnabled()) {
            log.debug("Handling complete application");
        }

        ApplicationHolder.acquireReadLock();
        try {
            ApplicationsEventPublisher.sendCompleteApplicationsEvent(applications);
        } finally {
            ApplicationHolder.releaseReadLock();
        }
    }

    public static synchronized void handleApplicationCreated (Application application,
                                                              Set<ApplicationClusterContext> appClusterContexts) {

        ApplicationHolder.acquireWriteLock();

        Applications applications = ApplicationHolder.getApplications();

        try {
            if (applications.getApplication(application.getUniqueIdentifier()) == null) {
                CloudControllerClient.getInstance().createApplicationClusters(application.getUniqueIdentifier(),
                        appClusterContexts);
                ApplicationHolder.persistApplication(application);
               // startApplicationMonitor(application.getUniqueIdentifier());
            } else {
                log.warn("Application [ " + application.getUniqueIdentifier() + " ] already exists in Applications");
            }

        } finally {
            ApplicationHolder.releaseWriteLock();
        }

        ApplicationsEventPublisher.sendApplicationCreatedEvent(application);
    }

    public static void handleApplicationUndeployed (String applicationId) {

        Applications applications = ApplicationHolder.getApplications();

        ApplicationHolder.acquireWriteLock();
        Application applicationToRemove = applications.getApplication(applicationId);
        Set<ClusterDataHolder> clusterData = null;

        try {
            if (applicationToRemove != null) {
                clusterData = applicationToRemove.getClusterDataRecursively();
                ApplicationHolder.removeApplication(applicationId);
            } else {
                log.warn("Application [ " + applicationId + " ] not found among existing Applications");
            }

        } finally {
            ApplicationHolder.releaseWriteLock();
        }

        ApplicationsEventPublisher.sendApplicationUndeployedEvent(applicationId, clusterData);
    }

    public static void handleGroupTerminatedEvent(String appId, String groupId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        Group group = application.getGroupRecursively(groupId);
        if (group == null) {
            log.warn(String.format("Group %s does not exist",
                    groupId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            GroupStatus status = GroupStatus.Terminated;
            if (group.isStateTransitionValid(status)) {
                log.info("Group Terminated adding status started for " + group.getUniqueIdentifier());
                group.setStatus(status);
                //updating the groupMonitor
                updateGroupMonitor(appId, groupId, status);
                //publishing data
                ApplicationsEventPublisher.sendGroupTerminatedEvent(appId, groupId);
            } else {
                log.warn("Terminated is not in the possible state list of [group] " + groupId);
            }
            ApplicationHolder.persistApplication(application);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }

    public static void handleGroupActivatedEvent(String appId, String groupId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        Group group = application.getGroupRecursively(groupId);
        if (group == null) {
            log.warn(String.format("Group %s does not exist",
                    groupId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            GroupStatus status = GroupStatus.Active;
            if (group.isStateTransitionValid(status)) {
                log.info("Group Active adding status started for " + group.getUniqueIdentifier());
                group.setStatus(status);
                //updating the groupMonitor
                updateGroupMonitor(appId, groupId, status);
                //publishing data
                ApplicationsEventPublisher.sendGroupActivatedEvent(appId, groupId);
            } else {
                log.warn("Active is not in the possible state list of [group] " + groupId);
            }
            ApplicationHolder.persistApplication(application);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }

    public static void handleGroupCreatedEvent(String appId, String groupId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        Group group = application.getGroupRecursively(groupId);
        if (group == null) {
            log.warn(String.format("Group %s does not exist",
                    groupId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            GroupStatus status = GroupStatus.Created;
            if (group.isStateTransitionValid(status)) {
                log.info("Group created adding status started for " + group.getUniqueIdentifier());
                group.setStatus(status);
                //updating the groupMonitor
                updateGroupMonitor(appId, groupId, status);
                //publishing data
                ApplicationsEventPublisher.sendGroupCreatedEvent(appId, groupId);
            } else {
                log.warn("Created is not in the possible state list of [group] " + groupId);
            }
            ApplicationHolder.persistApplication(application);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }

    }

    public static void handleGroupInActivateEvent(String appId, String groupId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        Group group = application.getGroupRecursively(groupId);
        if (group == null) {
            log.warn(String.format("Group %s does not exist",
                    groupId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            GroupStatus status = GroupStatus.Inactive;
            if (group.isStateTransitionValid(status)) {
                log.info("Group Inactive adding status started for " + group.getUniqueIdentifier());
                group.setStatus(status);
                //updating the groupMonitor
                updateGroupMonitor(appId, groupId, status);
                //publishing data
                ApplicationsEventPublisher.sendGroupInActivateEvent(appId, groupId);
            } else {
                log.warn("Inactive is not in the possible state list of [group] " + groupId);
            }
            ApplicationHolder.persistApplication(application);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }

    public static void handleGroupTerminatingEvent(String appId, String groupId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        Group group = application.getGroupRecursively(groupId);
        if (group == null) {
            log.warn(String.format("Group %s does not exist",
                    groupId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            GroupStatus status = GroupStatus.Terminating;
            if (group.isStateTransitionValid(status)) {
                log.info("Group Terminating adding status started for " + group.getUniqueIdentifier());
                group.setStatus(status);
                //updating the groupMonitor
                updateGroupMonitor(appId, groupId, status);
                //publishing data
                ApplicationsEventPublisher.sendGroupTerminatingEvent(appId, groupId);
            } else {
                log.warn("Terminating is not in the possible state list of [group] " + groupId);
            }
            ApplicationHolder.persistApplication(application);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }

    public static void handleApplicationActivatedEvent(String appId) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(appId);
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    appId));
            return;
        }

        try {
            ApplicationHolder.acquireWriteLock();
            ApplicationStatus status = ApplicationStatus.Active;
            if(application.isStateTransitionValid(status)) {
                application.setStatus(status);
                updateApplicationMonitor(appId, status);
                log.info("Application activated adding status started for Applications");
                ApplicationHolder.persistApplication(application);
                //publishing data
                ApplicationsEventPublisher.sendApplicationActivatedEvent(appId);
            }
        } finally {
            ApplicationHolder.releaseWriteLock();
        }

    }

    /*public static void handleApplicationCreatedEvent(ApplicationCreatedEvent event) {
        Applications applications = ApplicationHolder.getApplications();
        Application application = applications.getApplication(event.getAppId());
        //update the status of the Group
        if (application == null) {
            log.warn(String.format("Application %s does not exist",
                    event.getAppId()));
            return;
        }
        List<Cluster> clusters = new ArrayList<Cluster>();
        Set<ClusterDataHolder> allClusters = application.getClusterDataRecursively();

        for (ClusterDataHolder clusterDataHolder : allClusters) {
            String clusterId = clusterDataHolder.getClusterId();
            String serviceName = clusterDataHolder.getServiceType();
            clusters.add(ApplicationHolder.getApplications().getService(serviceName).getCluster(clusterId));
        }
        org.apache.stratos.messaging.event.applications.ApplicationCreatedEvent applicationActivatedEvent =
                new org.apache.stratos.messaging.event.applications.ApplicationCreatedEvent(
                        application, clusters);
        try {
            ApplicationHolder.acquireWriteLock();
            application.setStatus(ApplicationStatus.Created);
            log.info("Application created adding status started for Applications");

            ApplicationHolder.persistApplication(applications);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }
        //publishing data
        ApplicationsEventPublisher.sendApplicationCreatedEvent(applicationActivatedEvent);
    }*/

    public static void handleApplicationTerminatingEvent(String appId) {

        String applicationId = appId;

        // update the Application Status as 'Terminating'
        ApplicationHolder.acquireWriteLock();

        try {

            Applications applications = ApplicationHolder.getApplications();

            if (!applications.applicationExists(applicationId)) {
                log.warn("Application with id [ " + applicationId + " ] doesn't exist in Applications");
                return;
            }

            Application application = applications.getApplication(applicationId);
            // check and update application status to 'Terminating'
            ApplicationStatus status = ApplicationStatus.Terminating;
            if (!application.isStateTransitionValid(status)) {
                log.error("Invalid state transfer from " + application.getStatus() + " to " + ApplicationStatus.Terminating);
            }
            // for now anyway update the status forcefully
            application.setStatus(status);
            log.info("Application " + applicationId + "'s status updated to " + ApplicationStatus.Terminating);
            updateApplicationMonitor(appId, status);
            ApplicationsEventPublisher.sendApplicationTerminatingEvent(applicationId);
        } finally {
            ApplicationHolder.releaseWriteLock();
        }

    }

    private static void updateGroupStatusesRecursively(GroupStatus groupStatus, Collection<Group> groups) {

        for (Group group : groups) {
            if (!group.isStateTransitionValid(groupStatus)) {
                log.error("Invalid state transfer from " + group.getStatus() + " to " + groupStatus);
            }
            // force update for now
            group.setStatus(groupStatus);

            // go recursively and update
            if (group.getGroups() != null) {
                updateGroupStatusesRecursively(groupStatus, group.getGroups());
            }
        }
    }

    public static void handleApplicationTerminatedEvent(String appId) {

        Applications applications = ApplicationHolder.getApplications();

        try {
            ApplicationHolder.acquireWriteLock();

            if (!applications.applicationExists(appId)) {
                log.warn("Application with id [ " + appId + " ] doesn't exist in Applications");
                //ApplicationsEventPublisher.sendApplicationRemovedEvent(applicationId, tenantId, tenantDomain);

            } else {
                Application application = applications.getApplication(appId);

                if (!application.isStateTransitionValid(ApplicationStatus.Terminated)) {
                    log.error("Invalid status change from " + application.getStatus() + " to " + ApplicationStatus.Terminated);
                }
                // forcefully set status for now
                application.setStatus(ApplicationStatus.Terminated);
                updateApplicationMonitor(appId, ApplicationStatus.Terminated);

                int tenantId = application.getTenantId();
                String tenantDomain = application.getTenantDomain();
                Set<ClusterDataHolder> clusterData = application.getClusterDataRecursively();
                // remove clusters
                /*for (ClusterDataHolder clusterDataHolder : clusterData) {
                    Service service = applications.getService(clusterDataHolder.getServiceType());
                    if (service != null) {
                        // remove Cluster
                        service.removeCluster(clusterDataHolder.getClusterId());

                        if (log.isDebugEnabled()) {
                            log.debug("Removed cluster with id " + clusterDataHolder.getClusterId());
                        }
                    } else {
                        log.warn("Unable to remove cluster with cluster id: " + clusterDataHolder.getClusterId() + " from Applications, " +
                                " associated Service [ " + clusterDataHolder.getServiceType() + " ] npt found");
                    }

                    // remove runtime data
                    FasterLookUpDataHolder dataHolder = FasterLookUpDataHolder.getInstance();
                    dataHolder.removeClusterContext(clusterDataHolder.getClusterId());
                    if (log.isDebugEnabled()) {
                        log.debug("Removed Cluster Context for Cluster id: " + clusterDataHolder.getClusterId());
                    }

                    try {
                        RegistryManager.getInstance().persist(dataHolder);
                    } catch (RegistryException e) {
                        log.error("Unable to persist data in Registry", e);
                    }
                }


                // remove application
                applications.removeApplication(event.getAppId());
                ApplicationHolder.persistApplication(applications);

                deleteAppResourcesFromMetadataService(event);

                log.info("Removed application [ " + event.getAppId() + " ] from Applications");

                ApplicationsEventPublisher.sendApplicationTerminatedEvent(new org.apache.stratos.messaging.event.applications.ApplicationTerminatedEvent(event.getAppId(),
                        clusterData, tenantId, tenantDomain))*/
                ;
            }

        } finally {
            ApplicationHolder.releaseWriteLock();
        }
    }


    protected static synchronized void startApplicationMonitor(String appId) {

        ApplicationMonitor applicationMonitor = null;
        int retries = 5;
        boolean success = false;
        do {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e1) {
            }
            try {
                long start = System.currentTimeMillis();
                if (log.isDebugEnabled()) {
                    log.debug("application monitor is going to be started for [application] " +
                            appId);
                }
                applicationMonitor = ApplicationMonitorFactory.getApplicationMonitor(appId);

                long end = System.currentTimeMillis();
                log.info("Time taken to start app monitor: " + (end - start) / 1000);
                success = true;
            } catch (DependencyBuilderException e) {
                String msg = "Application monitor creation failed for Application: ";
                log.warn(msg, e);
                retries--;
            } catch (TopologyInConsistentException e) {
                String msg = "Application monitor creation failed for Application: ";
                log.warn(msg, e);
                retries--;
            }
        } while (!success && retries != 0);

        if (applicationMonitor == null) {
            String msg = "Application monitor creation failed, even after retrying for 5 times, "
                    + "for Application: " + appId;
            log.error(msg);
            throw new RuntimeException(msg);
        }

        AutoscalerContext.getInstance().addAppMonitor(applicationMonitor);

        if (log.isInfoEnabled()) {
            log.info(String.format("Application monitor has been added successfully: " +
                    "[application] %s", applicationMonitor.getId()));
        }
    }


        /*Thread th = null;
        if (!AutoscalerContext.getInstance()
                .appMonitorExist(applicationId)) {
            th = new Thread(
                    new ApplicationMonitorAdder(applicationId));
        }

        if (th != null) {
            th.start();
            //    try {
            //        th.join();
            //    } catch (InterruptedException ignore) {

            if (log.isDebugEnabled()) {
                log.debug(String
                        .format("Application monitor thread has been started successfully: " +
                                "[application] %s ", applicationId));
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug(String
                        .format("Application monitor thread already exists: " +
                                "[application] %s ", applicationId));
            }
        }*/


    private class ApplicationMonitorAdder implements Runnable {
        private String appId;

        public ApplicationMonitorAdder(String appId) {
            this.appId = appId;
        }

        public void run() {
            ApplicationMonitor applicationMonitor = null;
            int retries = 5;
            boolean success = false;
            do {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e1) {
                }
                try {
                    long start = System.currentTimeMillis();
                    if (log.isDebugEnabled()) {
                        log.debug("application monitor is going to be started for [application] " +
                                appId);
                    }
                    applicationMonitor = ApplicationMonitorFactory.getApplicationMonitor(appId);

                    long end = System.currentTimeMillis();
                    log.info("Time taken to start app monitor: " + (end - start) / 1000);
                    success = true;
                } catch (DependencyBuilderException e) {
                    String msg = "Application monitor creation failed for Application: ";
                    log.warn(msg, e);
                    retries--;
                } catch (TopologyInConsistentException e) {
                    String msg = "Application monitor creation failed for Application: ";
                    log.warn(msg, e);
                    retries--;
                }
            } while (!success && retries != 0);

            if (applicationMonitor == null) {
                String msg = "Application monitor creation failed, even after retrying for 5 times, "
                        + "for Application: " + appId;
                log.error(msg);
                throw new RuntimeException(msg);
            }

            AutoscalerContext.getInstance().addAppMonitor(applicationMonitor);

            if (log.isInfoEnabled()) {
                log.info(String.format("Application monitor has been added successfully: " +
                        "[application] %s", applicationMonitor.getId()));
            }
        }
    }


    private static void updateApplicationMonitor(String appId, ApplicationStatus status) {
        //Updating the Application Monitor
        ApplicationMonitor applicationMonitor = AutoscalerContext.getInstance().getAppMonitor(appId);
        if(applicationMonitor != null) {
            applicationMonitor.setStatus(status);
        } else {
            //TODO
        }

    }

    private static void updateGroupMonitor(String appId, String groupId, GroupStatus status) {
        //Updating the Application Monitor
        ApplicationMonitor applicationMonitor = AutoscalerContext.getInstance().getAppMonitor(appId);
        if(applicationMonitor != null) {
            GroupMonitor monitor = (GroupMonitor) applicationMonitor.findGroupMonitorWithId(groupId);
            if(monitor != null) {
                monitor.setStatus(status);
            } else {
                //TODO
            }
        }

    }
}
