/**
 * 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.ambari.server.serveraction.upgrades;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
import org.apache.ambari.server.orm.dao.HostVersionDAO;
import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
import org.apache.ambari.server.orm.dao.StackDAO;
import org.apache.ambari.server.orm.dao.UpgradeDAO;
import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.HostVersionEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
import org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity;
import org.apache.ambari.server.orm.entities.StackEntity;
import org.apache.ambari.server.orm.entities.UpgradeEntity;
import org.apache.ambari.server.serveraction.AbstractServerAction;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.ComponentInfo;
import org.apache.ambari.server.state.RepositoryVersionState;
import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.state.ServiceComponent;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.state.UpgradeState;
import org.apache.ambari.server.state.stack.upgrade.Direction;
import org.apache.ambari.server.state.svccomphost.ServiceComponentHostSummary;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrBuilder;

import com.google.inject.Inject;

/**
 * Action that represents finalizing the Upgrade by completing any database changes.
 */
public class FinalizeUpgradeAction extends AbstractServerAction {

  public static final String CLUSTER_NAME_KEY = "cluster_name";
  public static final String UPGRADE_DIRECTION_KEY = "upgrade_direction";
  public static final String VERSION_KEY = "version";
  public static final String REQUEST_ID = "request_id";
  public static final String PREVIOUS_UPGRADE_NOT_COMPLETED_MSG = "It is possible that a previous upgrade was not finalized. " +
      "For this reason, Ambari will not remove any configs. Please ensure that all database records are correct.";

  /**
   * The original "current" stack of the cluster before the upgrade started.
   * This is the same regardless of whether the current direction is
   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
   */
  public static final String ORIGINAL_STACK_KEY = "original_stack";

  /**
   * The target upgrade stack before the upgrade started. This is the same
   * regardless of whether the current direction is {@link Direction#UPGRADE} or
   * {@link Direction#DOWNGRADE}.
   */
  public static final String TARGET_STACK_KEY = "target_stack";

  /**
   * The Cluster that this ServerAction implementation is executing on
   */
  @Inject
  protected Clusters clusters;

  @Inject
  private ClusterVersionDAO clusterVersionDAO;

  @Inject
  private HostVersionDAO hostVersionDAO;

  @Inject
  private HostComponentStateDAO hostComponentStateDAO;

  /**
   * Gets {@link StackEntity} instances from {@link StackId}.
   */
  @Inject
  private StackDAO stackDAO;

  /**
   * Gets desired state entities for service components.
   */
  @Inject
  private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;

  /**
   * Gets {@link UpgradeEntity} instances.
   */
  @Inject
  private UpgradeDAO upgradeDAO;

  @Inject
  private AmbariMetaInfo ambariMetaInfo;

  @Override
  public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
      throws AmbariException, InterruptedException {

    Map<String, String> commandParams = getExecutionCommand().getCommandParams();

    boolean isDowngrade = commandParams.containsKey(UPGRADE_DIRECTION_KEY) &&
        "downgrade".equals(commandParams.get(UPGRADE_DIRECTION_KEY).toLowerCase());

    String version = commandParams.get(VERSION_KEY);
    StackId originalStackId = new StackId(commandParams.get(ORIGINAL_STACK_KEY));
    StackId targetStackId = new StackId(commandParams.get(TARGET_STACK_KEY));

    String clusterName = getExecutionCommand().getClusterName();

    if (isDowngrade) {
      return finalizeDowngrade(clusterName, originalStackId, targetStackId, version);
    } else {
      return finalizeUpgrade(clusterName, version, commandParams);
    }
  }

  /**
   * Execution path for upgrade.
   * @param clusterName the name of the cluster the upgrade is for
   * @param version     the target version of the upgrade
   * @return the command report
   */
  private CommandReport finalizeUpgrade(String clusterName, String version,
      Map<String, String> commandParams)
    throws AmbariException, InterruptedException {

    StringBuilder outSB = new StringBuilder();
    StringBuilder errSB = new StringBuilder();

    try {
      outSB.append(MessageFormat.format("Begin finalizing the upgrade of cluster {0} to version {1}\n", clusterName, version));

      Cluster cluster = clusters.getCluster(clusterName);
      StackId clusterDesiredStackId = cluster.getDesiredStackVersion();
      StackId clusterCurrentStackId = cluster.getCurrentStackVersion();

      ClusterVersionEntity upgradingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(
          clusterName, clusterDesiredStackId, version);

      if (upgradingClusterVersion == null) {
        throw new AmbariException(MessageFormat.format(
            "Cluster stack version {0} not found", version));
      }

      // Validate that all of the hosts with a version in the cluster have the
      // version being upgraded to, and it is in an allowed state.
      List<HostVersionEntity> hostVersions = hostVersionDAO.findByClusterStackAndVersion(
          clusterName, clusterDesiredStackId, version);

      // Will include hosts whose state is INSTALLED
      Set<HostVersionEntity> hostVersionsAllowed = new HashSet<HostVersionEntity>();
      Set<String> hostsWithoutCorrectVersionState = new HashSet<String>();
      Set<String> hostsToUpdate = new HashSet<String>();

      // It is important to only iterate over the hosts with a version, as
      // opposed to all hosts, since some hosts may only have components that do
      // not advertise a version, such as AMBARI_METRICS.
      for (HostVersionEntity hostVersion : hostVersions) {
        boolean hostHasCorrectVersionState = false;
        RepositoryVersionState hostVersionState = hostVersion.getState();
        switch( hostVersionState ){
          case CURRENT:{
            // if the state is correct, then do nothing
            hostHasCorrectVersionState = true;
            break;
          }
          case NOT_REQUIRED:
          case INSTALLED:{
            // It is possible that the host version has a state of INSTALLED and it
            // never changed if the host only has components that do not advertise a
            // version.
            HostEntity host = hostVersion.getHostEntity();

            ServiceComponentHostSummary hostSummary = new ServiceComponentHostSummary(ambariMetaInfo,
                host, clusterDesiredStackId);

            // if all components have finished advertising their version, then
            // this host can be considered upgraded
            if (hostSummary.haveAllComponentsFinishedAdvertisingVersion()) {
              // mark this as upgraded
              hostHasCorrectVersionState = true;
            } else {
              hostsWithoutCorrectVersionState.add(hostVersion.getHostName());
            }

            break;
          }
          default: {
            // all other states are not allowed
            hostsWithoutCorrectVersionState.add(hostVersion.getHostName());
            break;
          }
        }

        // keep track of this host version in order to transition it correctly
        if (hostHasCorrectVersionState) {
          hostVersionsAllowed.add(hostVersion);
          hostsToUpdate.add(hostVersion.getHostName());
        }
      }

      // throw an exception if there are hosts which are not not fully upgraded
      if (hostsWithoutCorrectVersionState.size() > 0) {
        String message = String.format("The following %d host(s) have not been upgraded to version %s. " +
                "Please install and upgrade the Stack Version on those hosts and try again.\nHosts: %s\n",
            hostsWithoutCorrectVersionState.size(),
            version,
            StringUtils.join(hostsWithoutCorrectVersionState, ", "));
        outSB.append(message);
        throw new AmbariException(message);
      }

      // iterate through all host components and make sure that they are on the
      // correct version; if they are not, then this will throw an exception
      List<InfoTuple> errors = checkHostComponentVersions(cluster, version, clusterDesiredStackId);
      if (! errors.isEmpty()) {
        StrBuilder messageBuff = new StrBuilder(
            String.format(
                "The following %d host component(s) "
                    + "have not been upgraded to version %s. Please install and upgrade "
                    + "the Stack Version on those hosts and try again.\nHost components:\n",
                errors.size(), version));

        for (InfoTuple error : errors) {
          messageBuff.append(String.format("%s on host %s\n", error.componentName, error.hostName));
        }

        throw new AmbariException(messageBuff.toString());
      }


      // we're guaranteed to be ready transition to upgraded now; ensure that
      // the transition will be allowed if the cluster state is not upgraded
      upgradingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName,
          clusterDesiredStackId, version);

      if (RepositoryVersionState.INSTALLING == upgradingClusterVersion.getState()) {
        cluster.transitionClusterVersion(clusterDesiredStackId, version, RepositoryVersionState.INSTALLED);

        upgradingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(
            clusterName, clusterDesiredStackId, version);
      }

      // we cannot finalize since the cluster was not ready to move into the
      // upgraded state
      if (RepositoryVersionState.INSTALLED != upgradingClusterVersion.getState()) {
        throw new AmbariException(String.format("The cluster stack version state %s is not allowed to transition directly into %s",
            upgradingClusterVersion.getState(), RepositoryVersionState.CURRENT.toString()));
      }

      outSB.append(
          String.format("Finalizing the upgraded state of host components in %d host(s).\n",
              hostVersionsAllowed.size()));

      // Reset the upgrade state
      for (HostVersionEntity hostVersion : hostVersionsAllowed) {
        Collection<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(hostVersion.getHostName());
        for (HostComponentStateEntity hostComponentStateEntity: hostComponentStates) {
          hostComponentStateEntity.setUpgradeState(UpgradeState.NONE);
          hostComponentStateDAO.merge(hostComponentStateEntity);
        }
      }

      // Impacts all hosts that have a version
      outSB.append(
          String.format("Finalizing the version for %d host(s).\n", hostVersionsAllowed.size()));
      cluster.mapHostVersions(hostsToUpdate, upgradingClusterVersion, RepositoryVersionState.CURRENT);

      // Reset upgrade state
      cluster.setUpgradeEntity(null);

      // transitioning the cluster into CURRENT will update the current/desired
      // stack values
      outSB.append(String.format("Finalizing the version for cluster %s.\n", clusterName));
      cluster.transitionClusterVersion(clusterDesiredStackId, version,
          RepositoryVersionState.CURRENT);

      if (commandParams.containsKey(REQUEST_ID)) {
        String requestId = commandParams.get(REQUEST_ID);
        UpgradeEntity upgradeEntity = upgradeDAO.findUpgradeByRequestId(Long.valueOf(requestId));

        if (null != upgradeEntity) {
          outSB.append("Creating upgrade history.\n");
          writeComponentHistory(cluster, upgradeEntity, clusterCurrentStackId,
              clusterDesiredStackId);
        } else {
          String warning = String.format(
              "Unable to create upgrade history because no upgrade could be found for request with ID %s\n",
              requestId);

          outSB.append(warning);
        }
      }

      outSB.append("Upgrade was successful!\n");
      return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString());
    } catch (Exception e) {
      errSB.append(e.getMessage());
      return createCommandReport(-1, HostRoleStatus.FAILED, "{}", outSB.toString(), errSB.toString());
    }
  }

  /**
   * Execution path for downgrade.
   *
   * @param clusterName
   *          the name of the cluster the downgrade is for
   * @paran originalStackId the stack ID of the cluster before the upgrade.
   * @paran targetStackId the stack ID that was desired for this upgrade.
   * @param version
   *          the target version of the downgrade
   * @return the command report
   */
  private CommandReport finalizeDowngrade(String clusterName,
      StackId originalStackId, StackId targetStackId, String version)
      throws AmbariException, InterruptedException {

    StringBuilder out = new StringBuilder();
    StringBuilder err = new StringBuilder();

    try {
      Cluster cluster = clusters.getCluster(clusterName);
      StackId currentClusterStackId = cluster.getCurrentStackVersion();

      // Safety check that the cluster's stack (from clusterstate's current_stack_id) is equivalent to the
      // cluster's CURRENT repo version's stack. This is to avoid deleting configs from the target stack if the customer
      // ended up modifying their database manually after a stack upgrade and forgot to call "Save DB State".
      ClusterVersionEntity currentClusterVersion = cluster.getCurrentClusterVersion();
      RepositoryVersionEntity currentRepoVersion = currentClusterVersion.getRepositoryVersion();
      StackId currentRepoStackId = currentRepoVersion.getStackId();
      if (!currentRepoStackId.equals(originalStackId)) {
        String msg = String.format("The stack of Cluster %s's CURRENT repo version is %s, yet the original stack id from " +
            "the Stack Upgrade has a different value of %s. %s",
            clusterName, currentRepoStackId.getStackId(), originalStackId.getStackId(), PREVIOUS_UPGRADE_NOT_COMPLETED_MSG);
        out.append(msg);
        err.append(msg);
        throw new AmbariException("The source target stack doesn't match the cluster's CURRENT repo version's stack.");
      }

      // This was a cross-stack upgrade, meaning that configurations were created that now need to be removed.
      if (!originalStackId.equals(targetStackId)) {
        out.append(String.format("Will remove configs since the original stack %s differs from the target stack %s " +
            "that Ambari just downgraded from.", originalStackId.getStackId(), targetStackId.getStackId()));
        cluster.removeConfigurations(targetStackId);
      }

      // !!! find and make sure the cluster_version EXCEPT current are set back
      out.append(String.format("Searching for current version for %s\n",
          clusterName));

      ClusterVersionEntity clusterVersion = clusterVersionDAO.findByClusterAndStateCurrent(clusterName);
      if (null == clusterVersion) {
        throw new AmbariException("Could not find current cluster version");
      }

      out.append(String.format("Comparing downgrade version %s to current cluster version %s\n",
          version,
          clusterVersion.getRepositoryVersion().getVersion()));

      if (!version.equals(clusterVersion.getRepositoryVersion().getVersion())) {
        throw new AmbariException(
            String.format("Downgrade version %s is not the current cluster version of %s",
                version, clusterVersion.getRepositoryVersion().getVersion()));
      } else {
        out.append(String.format("Downgrade version is the same as current.  Searching " +
          "for cluster versions that do not match %s\n", version));
      }

      Set<String> badVersions = new HashSet<String>();

      // update the cluster version
      for (ClusterVersionEntity cve : clusterVersionDAO.findByCluster(clusterName)) {
        switch (cve.getState()) {
          case INSTALL_FAILED:
          case INSTALLED:
          case INSTALLING: {
              badVersions.add(cve.getRepositoryVersion().getVersion());
              cve.setState(RepositoryVersionState.INSTALLED);
              clusterVersionDAO.merge(cve);
              break;
            }
          default:
            break;
        }
      }

      out.append(String.format("Found %d other version(s) not matching downgrade: %s\n",
          badVersions.size(), StringUtils.join(badVersions, ", ")));

      Set<String> badHosts = new HashSet<String>();
      for (String badVersion : badVersions) {
        List<HostVersionEntity> hostVersions = hostVersionDAO.findByClusterStackAndVersion(
            clusterName, targetStackId, badVersion);

        for (HostVersionEntity hostVersion : hostVersions) {
          badHosts.add(hostVersion.getHostName());
          hostVersion.setState(RepositoryVersionState.INSTALLED);
          hostVersionDAO.merge(hostVersion);
        }
      }

      out.append(String.format("Found %d hosts not matching downgrade version: %s\n",
          badHosts.size(), version));

      for (String badHost : badHosts) {
        List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(badHost);
        for (HostComponentStateEntity hostComponentState : hostComponentStates) {
          hostComponentState.setUpgradeState(UpgradeState.NONE);
          hostComponentStateDAO.merge(hostComponentState);
        }
      }

      // ensure that when downgrading, we set the desired back to the
      // original value
      cluster.setDesiredStackVersion(currentClusterStackId);
      // Reset upgrade state
      cluster.setUpgradeEntity(null);

      return createCommandReport(0, HostRoleStatus.COMPLETED, "{}",
          out.toString(), err.toString());

    } catch (Exception e) {
      StringWriter sw = new StringWriter();
      e.printStackTrace(new PrintWriter(sw));
      err.append(sw.toString());

      return createCommandReport(-1, HostRoleStatus.FAILED, "{}",
          out.toString(), err.toString());
    }
  }


  /**
   * Confirms that all host components that are able to provide hdp version,
   * have been upgraded to the target version.
   * @param cluster         the cluster the upgrade is for
   * @param desiredVersion  the target version of the upgrade
   * @param targetStackId     the target stack id for meta-info lookup
   * @return the list of {@link InfoTuple} objects of host components in error
   */
  protected List<InfoTuple> checkHostComponentVersions(Cluster cluster, String desiredVersion, StackId targetStackId)
          throws AmbariException {

    ArrayList<InfoTuple> errors = new ArrayList<InfoTuple>();

    for (Service service : cluster.getServices().values()) {
      for (ServiceComponent serviceComponent : service.getServiceComponents().values()) {
        for (ServiceComponentHost serviceComponentHost : serviceComponent.getServiceComponentHosts().values()) {
          ComponentInfo componentInfo = ambariMetaInfo.getComponent(targetStackId.getStackName(),
                  targetStackId.getStackVersion(), service.getName(), serviceComponent.getName());

          if (!componentInfo.isVersionAdvertised()) {
            StackId desired = serviceComponentHost.getDesiredStackVersion();
            StackId actual = serviceComponentHost.getStackVersion();
            if (!desired.equals(actual)) {
              serviceComponentHost.setStackVersion(desired);
            }
          } else if (componentInfo.isVersionAdvertised()
              && !serviceComponentHost.getVersion().equals(desiredVersion)) {
            errors.add(new InfoTuple(
                service.getName(), serviceComponent.getName(),
                serviceComponentHost.getHostName(), serviceComponentHost.getVersion()));
          }
        }
      }
    }

    return errors;
  }

  private void writeComponentHistory(Cluster cluster, UpgradeEntity upgradeEntity,
      StackId fromStackId, StackId toStackId) {

    StackEntity fromStack = stackDAO.find(fromStackId.getStackName(), fromStackId.getStackVersion());
    StackEntity toStack = stackDAO.find(toStackId.getStackName(), toStackId.getStackVersion());

    // for every service component, if it was included in the upgrade then
    // create a historical entry
    for (Service service : cluster.getServices().values()) {
      for (ServiceComponent serviceComponent : service.getServiceComponents().values()) {
        if (serviceComponent.isVersionAdvertised()) {
          // create the historical entry
          ServiceComponentHistoryEntity historyEntity = new ServiceComponentHistoryEntity();
          historyEntity.setUpgrade(upgradeEntity);
          historyEntity.setFromStack(fromStack);
          historyEntity.setToStack(toStack);

          // get the service component
          ServiceComponentDesiredStateEntity desiredStateEntity = serviceComponentDesiredStateDAO.findByName(
              cluster.getClusterId(), serviceComponent.getServiceName(),
              serviceComponent.getName());

          // add the history to the component and save
          desiredStateEntity.addHistory(historyEntity);
          serviceComponentDesiredStateDAO.merge(desiredStateEntity);
        }
      }
    }
  }

  protected static class InfoTuple {
    protected final String serviceName;
    protected final String componentName;
    protected final String hostName;
    protected final String currentVersion;

    protected InfoTuple(String service, String component, String host, String version) {
      serviceName = service;
      componentName = component;
      hostName = host;
      currentVersion = version;
    }
  }

}
