/*
 * 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.dao;

import com.epam.dlab.auth.UserInfo;
import com.epam.dlab.backendapi.domain.ProjectDTO;
import com.epam.dlab.dto.UserInstanceStatus;
import com.epam.dlab.dto.base.edge.EdgeInfo;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.mongodb.BasicDBObject;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.elemMatch;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Filters.in;
import static com.mongodb.client.model.Filters.not;

public class ProjectDAOImpl extends BaseDAO implements ProjectDAO {

	private static final String PROJECTS_COLLECTION = "Projects";
	private static final String GROUPS = "groups";
	private static final String ENDPOINTS = "endpoints";
	private static final String STATUS_FIELD = "status";
	private static final String SHARED_IMAGE_FIELD = "sharedImageEnabled";
	private static final String ENDPOINT_STATUS_FIELD = "endpoints." + STATUS_FIELD;
	private static final String EDGE_INFO_FIELD = "edgeInfo";
	private static final String ENDPOINT_FIELD = "endpoints.$.";
	private static final String ANYUSER = Pattern.quote("$anyuser");

	private final UserGroupDao userGroupDao;

	@Inject
	public ProjectDAOImpl(UserGroupDao userGroupDao) {
		this.userGroupDao = userGroupDao;
	}


	@Override
	public List<ProjectDTO> getProjects() {
		return find(PROJECTS_COLLECTION, ProjectDTO.class);
	}

	@Override
	public List<ProjectDTO> getProjectsWithEndpointStatusNotIn(UserInstanceStatus... statuses) {
		final List<String> statusList =
				Arrays.stream(statuses).map(UserInstanceStatus::name).collect(Collectors.toList());

		return find(PROJECTS_COLLECTION, not(in(ENDPOINT_STATUS_FIELD, statusList)), ProjectDTO.class);
	}

	@Override
	public List<ProjectDTO> getUserProjects(UserInfo userInfo, boolean active) {
		final Set<String> groups = Stream.concat(userGroupDao.getUserGroups(userInfo.getName()).stream(),
				userInfo.getRoles().stream())
				.collect(Collectors.toSet());
		return find(PROJECTS_COLLECTION, userProjectCondition(groups, active), ProjectDTO.class);
	}

	@Override
	public void create(ProjectDTO projectDTO) {
		insertOne(PROJECTS_COLLECTION, projectDTO);
	}

	@Override
	public void updateStatus(String projectName, ProjectDTO.Status status) {
		updateOne(PROJECTS_COLLECTION, projectCondition(projectName),
				new Document(SET, new Document(STATUS_FIELD, status.toString())));
	}

	@Override
	public void updateEdgeStatus(String projectName, String endpoint, UserInstanceStatus status) {
		BasicDBObject dbObject = new BasicDBObject();
		dbObject.put(ENDPOINT_FIELD + STATUS_FIELD, status.name());
		updateOne(PROJECTS_COLLECTION, projectAndEndpointCondition(projectName,
				endpoint), new Document(SET, dbObject));
	}

	@Override
	public void updateEdgeInfo(String projectName, String endpointName, EdgeInfo edgeInfo) {
		BasicDBObject dbObject = new BasicDBObject();
		dbObject.put(ENDPOINT_FIELD + STATUS_FIELD, UserInstanceStatus.RUNNING.name());
		dbObject.put(ENDPOINT_FIELD + EDGE_INFO_FIELD, convertToBson(edgeInfo));
		updateOne(PROJECTS_COLLECTION, projectAndEndpointCondition(projectName, endpointName), new Document(SET,
				dbObject));
	}

	@Override
	public Optional<ProjectDTO> get(String name) {
		return findOne(PROJECTS_COLLECTION, projectCondition(name), ProjectDTO.class);
	}

	@Override
	public List<ProjectDTO> getProjectsByEndpoint(String endpointName) {
		return find(PROJECTS_COLLECTION, elemMatch(ENDPOINTS, eq("name", endpointName)), ProjectDTO.class);
	}

	@Override
	public boolean update(ProjectDTO projectDTO) {
		BasicDBObject updateProject = new BasicDBObject();
		updateProject.put(GROUPS, projectDTO.getGroups());
		updateProject.put(ENDPOINTS,
				projectDTO.getEndpoints().stream().map(this::convertToBson).collect(Collectors.toList()));
		updateProject.put(SHARED_IMAGE_FIELD, projectDTO.isSharedImageEnabled());
		return updateOne(PROJECTS_COLLECTION, projectCondition(projectDTO.getName()),
				new Document(SET, updateProject)).getMatchedCount() > 0L;
	}

	@Override
	public void remove(String name) {
		deleteOne(PROJECTS_COLLECTION, projectCondition(name));
	}

	@Override
	public Optional<Integer> getAllowedBudget(String project) {
		return get(project).map(ProjectDTO::getBudget);
	}

	@Override
	public void updateBudget(String project, Integer budget) {
		updateOne(PROJECTS_COLLECTION, projectCondition(project), new Document(SET, new Document("budget", budget)));
	}

	@Override
	public boolean isAnyProjectAssigned(Set<String> groups) {
		final String groupsRegex = !groups.isEmpty() ? String.join("|", groups) + "|" + ANYUSER : ANYUSER;
		return !Iterables.isEmpty(find(PROJECTS_COLLECTION, elemMatch(GROUPS, regexCaseInsensitive(groupsRegex))));
	}

	private Bson projectCondition(String name) {
		return eq("name", name);
	}

	private Bson userProjectCondition(Set<String> groups, boolean active) {
		final String groupsRegex = !groups.isEmpty() ? String.join("|", groups) + "|" + ANYUSER : ANYUSER;
		if (active) {
			return and(elemMatch(GROUPS, regexCaseInsensitive(groupsRegex)),
					eq(ENDPOINT_STATUS_FIELD, UserInstanceStatus.RUNNING.name()));
		}
		return elemMatch(GROUPS, regexCaseInsensitive(groupsRegex));
	}

	private Bson projectAndEndpointCondition(String projectName, String endpointName) {
		return and(eq("name", projectName), eq("endpoints.name", endpointName));
	}

	private Document regexCaseInsensitive(String values) {
		return new Document("$regex",
				"^(" + values + ")$").append("$options", "i");
	}
}
