/*-
 * ~~~~~~licensing~~~~~~
 * profile-management-service-adapters
 * ==========
 * Copyright (C) 2020 - 2021 EmDev LLC
 * ==========
 * Licensed 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.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.esb.platform.core.management.profile.adapters;

import java.util.ArrayList;
import java.util.List;

import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;

import ru.entaxy.esb.system.core.permission.jpa.PermissionService;
import ru.entaxy.esb.system.core.permission.jpa.entity.Permission;
import ru.entaxy.esb.system.jpa.SystemService;
import ru.entaxy.esb.system.jpa.entity.System;
import ru.entaxy.esb.system.management.permission.manager.PermissionManager;
import ru.entaxy.esb.system.management.permission.manager.dto.PermissionDto;

@Component (service = ru.entaxy.esb.platform.core.management.profile.api.PermissionManager.class
, immediate = true)
public class PermissionManagerAdapter implements ru.entaxy.esb.platform.core.management.profile.api.PermissionManager {

	@Reference(service = PermissionManager.class, cardinality = ReferenceCardinality.MANDATORY
			, collectionType = CollectionType.SERVICE)
	PermissionManager permissionManager;
	
	@Reference(service = PermissionService.class, cardinality = ReferenceCardinality.MANDATORY
			, collectionType = CollectionType.SERVICE)
	PermissionService permissionService;

	@Reference (service = SystemService.class, cardinality = ReferenceCardinality.MANDATORY
			, collectionType = CollectionType.SERVICE)
	SystemService systemService;
	
	@Override
	public List<String> getObjectPermissions(String objectId) throws Exception {
		System system = getRequiredSystemByIdOrName(objectId);
		List<Permission> permissions = permissionService.getAllById(system.getId(), "system");
		long systemId = system.getId();
		List<String> result = new ArrayList<>();
		for (Permission perm: permissions) {
			if (perm.getObjectId() == systemId) {
				if ("system".equals(perm.getSubjectType())) {
					System s = systemService.get(Long.parseLong(perm.getSubjectId()));
					if (s != null)
						result.add(s.getName());
				}
			}
		}
		return result;
	}

	@Override
	public List<String> getSubjectPermissions(String subjectId) throws Exception {
		System system = getRequiredSystemByIdOrName(subjectId);
		List<Permission> permissions = permissionService.getAllById(system.getId(), "system");
		String systemId = system.getId() + "";
		List<String> result = new ArrayList<>();
		for (Permission perm: permissions) {
			if (perm.getSubjectId().equals(systemId)) {
				System s = systemService.get(perm.getObjectId());
				if (s != null)
					result.add(s.getName());
			}
		}
		return result;
	}

	@Override
	public void createPermission(String objectId, String subjectId) throws Exception {
		PermissionDto dto = new PermissionDto(objectId, subjectId);
		permissionManager.createPermission(dto);
	}

	protected System getSystemByIdOrName(String idOrName) {
		System result = systemService.getByName(idOrName);
		if (result == null)
			result = systemService.getByUuid(idOrName);
		return result;
	}

	protected System getRequiredSystemByIdOrName(String idOrName) throws Exception {
		System result = systemService.getByName(idOrName);
		if (result == null)
			result = systemService.getByUuid(idOrName);
		if (result == null)
			throw new IllegalArgumentException("System not found by Id or Name: [" + idOrName + "]");
		return result;
	}
	
}
