/*-
 * ~~~~~~licensing~~~~~~
 * artifact-management
 * ==========
 * 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.platform.core.artifact.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.karaf.cave.repository.RepositoryService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
import ru.entaxy.platform.core.artifact.installer.builder.InstallersWithDefaults;
import ru.entaxy.platform.core.artifact.installer.builder.impl.InstallersWithDefaultsImpl;
import ru.entaxy.platform.core.artifact.repository.ArtifactRepository;
import ru.entaxy.platform.core.artifact.repository.impl.ArtifactRepositoryImpl;
import ru.entaxy.platform.core.artifact.repository.impl.DeployedArtifactImpl;
import ru.entaxy.platform.core.artifact.repository.impl.RepositoryConfigurableHelper;
import ru.entaxy.platform.core.artifact.repository.impl.RepositoryConfigurableHelperCollector;
import ru.entaxy.platform.core.artifact.service.ArtifactService;

public class ArtifactServiceImpl implements ArtifactService, RepositoryConfigurableHelperCollector {
	
	protected Map<String, ArtifactRepository> repositories = new HashMap<>();
	
	protected BundleContext bundleContext;
	
	protected RepositoryService repositoryService;
	
	protected InstallersWithDefaultsImpl installers;
	
	private final static Logger log = LoggerFactory.getLogger(ArtifactServiceImpl.class);
	
	public ArtifactServiceImpl() {
		installers = new InstallersWithDefaultsImpl();
	}
	
	public void addRepository(ArtifactRepository repository) {
		
	}
	
	@Override
	public void addConfigurableHelper(RepositoryConfigurableHelper helper) {
		log.info("Added helper for repository [{}]", helper.getName());
		if (!repositories.containsKey(helper.getName())) {
			ArtifactRepository repo = createRepository(helper);
			this.repositories.put(repo.getName(), repo);
		}
	}

	protected ArtifactRepository createRepository(RepositoryConfigurableHelper helper) {
		ArtifactRepositoryImpl repo = new ArtifactRepositoryImpl(helper);
		synchronized (repositories) {
			repositories.put(repo.getName(), repo);
		}
		repo.setRepositoryService(repositoryService);
		repo.init();
		return repo;
	}
	
	@Override
	public DeployedArtifact deployLocal(Artifact artifact) {
		return deploy(artifact, ArtifactRepository.REPO_NAME_LOCAL);
	}

	@Override
	public DeployedArtifact deployShared(Artifact artifact) {
		return deploy(artifact, ArtifactRepository.REPO_NAME_SHARED);
	}

	// TODO refactor to using repository exceptions if needed
	protected DeployedArtifact deploy(Artifact artifact, String repositoryName) {
		String error = "Repository [" + repositoryName + "] not found";
		if (repositories.containsKey(repositoryName)) {
			ArtifactRepository repo = repositories.get(repositoryName);
			error = String.format("Cannot deploy artifact [%s] to repository [" + repositoryName + "]", artifact.getCoordinates().toString());
			if (repo.isHealthy())
				if (repo.isEnabled())
					if (!repo.isReadOnly())
						return repo.deploy(artifact);
					else
						error += ": repository is readonly";
				else
					error += ": repository is disabled";
			else
				error += ": repository is not healthy";
		}
		log.error(error);
		return new DeployedArtifactImpl(artifact);
	}
	
	@Override
	public ArtifactRepository getRepository(String name) {
		return this.repositories.get(name);
	}

	public void setBundleContext(BundleContext bundleContext) {
		this.bundleContext = bundleContext;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}
	
	@Override
	public InstallersWithDefaults installers() {
		return this.installers;
	}

	public void setInstallers(InstallersWithDefaultsImpl installers) {
		this.installers = installers;
	}
	
}
