/*
 * 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 com.epam.dlab.backendapi.service.impl;

import com.epam.dlab.auth.UserInfo;
import com.epam.dlab.backendapi.annotation.BudgetLimited;
import com.epam.dlab.backendapi.annotation.Project;
import com.epam.dlab.backendapi.dao.ComputationalDAO;
import com.epam.dlab.backendapi.dao.ExploratoryDAO;
import com.epam.dlab.backendapi.dao.GitCredsDAO;
import com.epam.dlab.backendapi.dao.ImageExploratoryDao;
import com.epam.dlab.backendapi.domain.RequestId;
import com.epam.dlab.backendapi.service.EndpointService;
import com.epam.dlab.backendapi.service.ExploratoryService;
import com.epam.dlab.backendapi.service.TagService;
import com.epam.dlab.backendapi.util.RequestBuilder;
import com.epam.dlab.constants.ServiceConsts;
import com.epam.dlab.dto.StatusEnvBaseDTO;
import com.epam.dlab.dto.UserInstanceDTO;
import com.epam.dlab.dto.UserInstanceStatus;
import com.epam.dlab.dto.aws.computational.ClusterConfig;
import com.epam.dlab.dto.computational.UserComputationalResource;
import com.epam.dlab.dto.exploratory.*;
import com.epam.dlab.exceptions.DlabException;
import com.epam.dlab.model.ResourceType;
import com.epam.dlab.model.exploratory.Exploratory;
import com.epam.dlab.model.library.Library;
import com.epam.dlab.rest.client.RESTService;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.epam.dlab.dto.UserInstanceStatus.*;
import static com.epam.dlab.rest.contracts.ExploratoryAPI.*;

@Slf4j
@Singleton
public class ExploratoryServiceImpl implements ExploratoryService {

	@Inject
	private ExploratoryDAO exploratoryDAO;
	@Inject
	private ComputationalDAO computationalDAO;
	@Inject
	private GitCredsDAO gitCredsDAO;
	@Inject
	private ImageExploratoryDao imageExploratoryDao;
	@Inject
	@Named(ServiceConsts.PROVISIONING_SERVICE_NAME)
	private RESTService provisioningService;
	@Inject
	private RequestBuilder requestBuilder;
	@Inject
	private RequestId requestId;
	@Inject
	private TagService tagService;
	@Inject
	private EndpointService endpointService;

	@BudgetLimited
	@Override
	public String start(UserInfo userInfo, String exploratoryName, @Project String project) {
		return action(userInfo, exploratoryName, EXPLORATORY_START, STARTING);
	}

	@Override
	public String stop(UserInfo userInfo, String exploratoryName) {
		return action(userInfo, exploratoryName, EXPLORATORY_STOP, STOPPING);
	}

	@Override
	public String terminate(UserInfo userInfo, String exploratoryName) {
		return action(userInfo, exploratoryName, EXPLORATORY_TERMINATE, TERMINATING);
	}

	@BudgetLimited
	@Override
	public String create(UserInfo userInfo, Exploratory exploratory, @Project String project) {
		boolean isAdded = false;
		try {
			final UserInstanceDTO userInstanceDTO = getUserInstanceDTO(userInfo, exploratory, project);
			exploratoryDAO.insertExploratory(userInstanceDTO);
			isAdded = true;
			final ExploratoryGitCredsDTO gitCreds = gitCredsDAO.findGitCreds(userInfo.getName());
			log.debug("Created exploratory environment {} for user {}", exploratory.getName(), userInfo.getName());
			final String uuid =
					provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + EXPLORATORY_CREATE,
							userInfo.getAccessToken(),
							requestBuilder.newExploratoryCreate(exploratory, userInfo, gitCreds,
									userInstanceDTO.getTags()),
							String.class);
			requestId.put(userInfo.getName(), uuid);
			return uuid;
		} catch (Exception t) {
			log.error("Could not update the status of exploratory environment {} with name {} for user {}",
					exploratory.getDockerImage(), exploratory.getName(), userInfo.getName(), t);
			if (isAdded) {
				updateExploratoryStatusSilent(userInfo.getName(), exploratory.getName(), FAILED);
			}
			throw new DlabException("Could not create exploratory environment " + exploratory.getName() + " for user "
					+ userInfo.getName() + ": " + t.getLocalizedMessage(), t);
		}
	}

	@Override
	public void updateExploratoryStatuses(String user, UserInstanceStatus status) {
		exploratoryDAO.fetchUserExploratoriesWhereStatusNotIn(user, TERMINATED, FAILED)
				.forEach(ui -> updateExploratoryStatus(ui.getExploratoryName(), status, user));
	}

	@Override
	public void updateProjectExploratoryStatuses(String project, String endpoint, UserInstanceStatus status) {
		exploratoryDAO.fetchProjectExploratoriesWhereStatusNotIn(project, endpoint, TERMINATED, FAILED)
				.forEach(ui -> updateExploratoryStatus(ui.getExploratoryName(), status, ui.getUser()));
	}

	/**
	 * Updates parameter 'reuploadKeyRequired' for corresponding user's exploratories with allowable statuses.
	 *
	 * @param user                user.
	 * @param reuploadKeyRequired true/false.
	 * @param exploratoryStatuses allowable exploratories' statuses.
	 */
	@Override
	public void updateExploratoriesReuploadKeyFlag(String user, boolean reuploadKeyRequired,
												   UserInstanceStatus... exploratoryStatuses) {
		exploratoryDAO.updateReuploadKeyForExploratories(user, reuploadKeyRequired, exploratoryStatuses);
	}

	/**
	 * Returns list of user's exploratories and corresponding computational resources where both of them have
	 * predefined statuses.
	 *
	 * @param user                user.
	 * @param exploratoryStatus   status for exploratory environment.
	 * @param computationalStatus status for computational resource affiliated with the exploratory.
	 * @return list with user instances.
	 */
	@Override
	public List<UserInstanceDTO> getInstancesWithStatuses(String user, UserInstanceStatus exploratoryStatus,
														  UserInstanceStatus computationalStatus) {
		return getExploratoriesWithStatus(user, exploratoryStatus).stream()
				.map(e -> e.withResources(computationalResourcesWithStatus(e, computationalStatus)))
				.collect(Collectors.toList());
	}

	@Override
	public void updateClusterConfig(UserInfo userInfo, String exploratoryName, List<ClusterConfig> config) {
		final String userName = userInfo.getName();
		final String token = userInfo.getAccessToken();
		final UserInstanceDTO userInstanceDTO = exploratoryDAO.fetchRunningExploratoryFields(userName,
				exploratoryName);
		final ExploratoryReconfigureSparkClusterActionDTO updateClusterConfigDTO =
				requestBuilder.newClusterConfigUpdate(userInfo, userInstanceDTO, config);
		final String uuid =
				provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + EXPLORATORY_RECONFIGURE_SPARK, token, updateClusterConfigDTO,
						String.class);
		requestId.put(userName, uuid);
		exploratoryDAO.updateExploratoryFields(new ExploratoryStatusDTO()
				.withUser(userName)
				.withExploratoryName(exploratoryName)
				.withConfig(config)
				.withStatus(UserInstanceStatus.RECONFIGURING.toString()));
	}

	/**
	 * Returns user instance's data by it's name.
	 *
	 * @param user            user.
	 * @param exploratoryName name of exploratory.
	 * @return corresponding user instance's data or empty data if resource doesn't exist.
	 */
	@Override
	public Optional<UserInstanceDTO> getUserInstance(String user, String exploratoryName) {
		try {
			return Optional.of(exploratoryDAO.fetchExploratoryFields(user, exploratoryName));
		} catch (DlabException e) {
			log.warn("User instance with exploratory name {} for user {} not found.", exploratoryName, user);
		}
		return Optional.empty();
	}

	@Override
	public List<ClusterConfig> getClusterConfig(UserInfo user, String exploratoryName) {
		return exploratoryDAO.getClusterConfig(user.getName(), exploratoryName);
	}


	private List<UserComputationalResource> computationalResourcesWithStatus(UserInstanceDTO userInstance,
																			 UserInstanceStatus computationalStatus) {
		return userInstance.getResources().stream()
				.filter(resource -> resource.getStatus().equals(computationalStatus.toString()))
				.collect(Collectors.toList());
	}

	/**
	 * Returns list of user's exploratories with predefined status.
	 *
	 * @param user   user.
	 * @param status status for exploratory environment.
	 * @return list of user's instances.
	 */
	private List<UserInstanceDTO> getExploratoriesWithStatus(String user, UserInstanceStatus status) {
		return exploratoryDAO.fetchUserExploratoriesWhereStatusIn(user, true, status);
	}

	/**
	 * Sends the post request to the provisioning service and update the status of exploratory environment.
	 *
	 * @param userInfo        user info.
	 * @param exploratoryName name of exploratory environment.
	 * @param action          action for exploratory environment.
	 * @param status          status for exploratory environment.
	 * @return Invocation request as JSON string.
	 */
	private String action(UserInfo userInfo, String exploratoryName, String action, UserInstanceStatus status) {
		try {
			updateExploratoryStatus(exploratoryName, status, userInfo.getName());

			UserInstanceDTO userInstance = exploratoryDAO.fetchExploratoryFields(userInfo.getName(), exploratoryName);
			final String uuid =
					provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + action,
							userInfo.getAccessToken(),
							getExploratoryActionDto(userInfo, status, userInstance), String.class);
			requestId.put(userInfo.getName(), uuid);
			return uuid;
		} catch (Exception t) {
			log.error("Could not " + action + " exploratory environment {} for user {}", exploratoryName, userInfo
					.getName(), t);
			updateExploratoryStatusSilent(userInfo.getName(), exploratoryName, FAILED);
			throw new DlabException("Could not " + action + " exploratory environment " + exploratoryName + ": " +
					t.getLocalizedMessage(), t);
		}
	}

	private void updateExploratoryStatus(String exploratoryName, UserInstanceStatus status, String user) {
		updateExploratoryStatus(user, exploratoryName, status);

		if (status == STOPPING) {
			updateComputationalStatuses(user, exploratoryName, STOPPING, TERMINATING, FAILED, TERMINATED, STOPPED);
		} else if (status == TERMINATING) {
			updateComputationalStatuses(user, exploratoryName, TERMINATING, TERMINATING, TERMINATED, FAILED);
		}
	}

	private ExploratoryActionDTO<?> getExploratoryActionDto(UserInfo userInfo, UserInstanceStatus status,
															UserInstanceDTO userInstance) {
		ExploratoryActionDTO<?> dto;
		if (status != UserInstanceStatus.STARTING) {
			dto = requestBuilder.newExploratoryStop(userInfo, userInstance);
		} else {
			dto = requestBuilder.newExploratoryStart(
					userInfo, userInstance, gitCredsDAO.findGitCreds(userInfo.getName()));

		}
		return dto;
	}


	/**
	 * Updates the status of exploratory environment.
	 *
	 * @param user            user name
	 * @param exploratoryName name of exploratory environment.
	 * @param status          status for exploratory environment.
	 */
	private void updateExploratoryStatus(String user, String exploratoryName, UserInstanceStatus status) {
		StatusEnvBaseDTO<?> exploratoryStatus = createStatusDTO(user, exploratoryName, status);
		exploratoryDAO.updateExploratoryStatus(exploratoryStatus);
	}

	/**
	 * Updates the status of exploratory environment without exceptions. If exception occurred then logging it.
	 *
	 * @param user            user name
	 * @param exploratoryName name of exploratory environment.
	 * @param status          status for exploratory environment.
	 */
	private void updateExploratoryStatusSilent(String user, String exploratoryName, UserInstanceStatus status) {
		try {
			updateExploratoryStatus(user, exploratoryName, status);
		} catch (DlabException e) {
			log.error("Could not update the status of exploratory environment {} for user {} to {}",
					exploratoryName, user, status, e);
		}
	}

	private void updateComputationalStatuses(String user, String exploratoryName, UserInstanceStatus
			dataEngineStatus, UserInstanceStatus dataEngineServiceStatus, UserInstanceStatus... excludedStatuses) {
		log.debug("updating status for all computational resources of {} for user {}: DataEngine {}, " +
				"dataengine-service {}", exploratoryName, user, dataEngineStatus, dataEngineServiceStatus);
		computationalDAO.updateComputationalStatusesForExploratory(user, exploratoryName, dataEngineStatus,
				dataEngineServiceStatus, excludedStatuses);
	}

	/**
	 * Instantiates and returns the descriptor of exploratory environment status.
	 *
	 * @param user            user name
	 * @param exploratoryName name of exploratory environment.
	 * @param status          status for exploratory environment.
	 */
	private StatusEnvBaseDTO<?> createStatusDTO(String user, String exploratoryName, UserInstanceStatus status) {
		return new ExploratoryStatusDTO()
				.withUser(user)
				.withExploratoryName(exploratoryName)
				.withStatus(status);
	}

	private UserInstanceDTO getUserInstanceDTO(UserInfo userInfo, Exploratory exploratory, String project) {
		final UserInstanceDTO userInstance = new UserInstanceDTO()
				.withUser(userInfo.getName())
				.withExploratoryName(exploratory.getName())
				.withStatus(CREATING.toString())
				.withImageName(exploratory.getDockerImage())
				.withImageVersion(exploratory.getVersion())
				.withTemplateName(exploratory.getTemplateName())
				.withClusterConfig(exploratory.getClusterConfig())
				.withShape(exploratory.getShape())
				.withProject(project)
				.withEndpoint(exploratory.getEndpoint())
				.withTags(tagService.getResourceTags(userInfo, exploratory.getEndpoint(), project,
						exploratory.getExploratoryTag()));
		if (StringUtils.isNotBlank(exploratory.getImageName())) {
			final List<LibInstallDTO> libInstallDtoList = getImageRelatedLibraries(userInfo, exploratory
					.getImageName());
			userInstance.withLibs(libInstallDtoList);
		}
		return userInstance;
	}

	private List<LibInstallDTO> getImageRelatedLibraries(UserInfo userInfo, String imageFullName) {
		final List<Library> libraries = imageExploratoryDao.getLibraries(userInfo.getName(), imageFullName,
				ResourceType.EXPLORATORY, LibStatus.INSTALLED);
		return toLibInstallDtoList(libraries);
	}

	private List<LibInstallDTO> toLibInstallDtoList(List<Library> libraries) {
		return libraries
				.stream()
				.map(this::toLibInstallDto)
				.collect(Collectors.toList());
	}

	private LibInstallDTO toLibInstallDto(Library l) {
		return new LibInstallDTO(l.getGroup(), l.getName(), l.getVersion())
				.withStatus(l.getStatus().toString())
				.withErrorMessage(l.getErrorMessage());
	}
}
