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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.config.core.ConfigRepository;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.esb.platform.runtime.core.initializer.api.AbstractInitializer;
import ru.entaxy.esb.platform.runtime.core.initializer.api.InitializerException;
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
import ru.entaxy.platform.core.artifact.service.ArtifactService;

public class ArtifactRepositoryInitializer extends AbstractInitializer {

	private static final Logger log = LoggerFactory.getLogger(ArtifactRepositoryInitializer.class);

	private static final String MVN_PID = "org.ops4j.pax.url.mvn";
	
	private static final String PROP_ENTAXY_REPO_LIST = "org.ops4j.pax.url.mvn.repositories.entaxy";
	
	private static final String ENTAXY_PROPERTY_HTTP_PORT = "entaxy.org.osgi.service.http.port";
	
	private ArtifactService artifactService = null;
		
	protected ConfigRepository configRepository;
	
	@Override
	public void init() throws InitializerException {
		ServiceReference<?>[] references = bundleContext.getBundle().getRegisteredServices();
		if (references != null)
			for (int i=0; i<references.length; i++) {
				Object objectClass = references[i].getProperty("objectClass");
				if (objectClass!=null) {
					String[] classes = (String[])objectClass;
					if (Arrays.asList(classes)
							.stream()
							.filter((s)->ArtifactService.class.getName().equals(s))
							.count() > 0) {
						try {
							artifactService = (ArtifactService)bundleContext.getService(references[i]);
							break;
						} catch (Exception e) {
							log.error("Error getting ArtifactService service from ServiceReference");
						}
					};
				};
			}
		if (artifactService == null)
			try {
				artifactService = OSGIUtils.services().ofClass(ArtifactService.class).waitService(20000).get();	
			} catch (Exception e) {
				throw new InitializerException(this, "ArtifactService not found", "", e);
			}
		
		if (artifactService == null) {
			throw new InitializerException(this, "ArtifactService not found", "", null);
		}

		
		List<String> repositoryUrls = new ArrayList<>();
		String urlPrefix = "http://localhost:${" + ENTAXY_PROPERTY_HTTP_PORT + "}";
		
		// check if 'local' and 'shared' repositories are defined

		ArtifactRepository repository = artifactService.getRepository(ArtifactRepository.REPO_NAME_LOCAL);
		if (!repository.isHealthy() || !repository.isEnabled()) {
			// TODO create own exceptions 
			throw new InitializerException(this
					, String.format("Repository [{}] is not healthy or not enabled", repository.getName())
					, "Please check the configuration", null);
		}
		// don't check sha1 or md5
		repositoryUrls.add(
				urlPrefix + repository.getUrl() 
				+ "@id=" + repository.getName() 
				+ "@checksum=ignore"
				+ (repository.isSnapshotsAllowed()?"@snapshots":"")
			);
		
		repository = artifactService.getRepository(ArtifactRepository.REPO_NAME_SHARED);
		if (!repository.isHealthy() || !repository.isEnabled()) {
			// TODO create own exceptions 
			throw new InitializerException(this
					, String.format("Repository [{}] is not healthy or not enabled", repository.getName())
					, "Please check the configuration", null);
		}
		// don't check sha1 or md5
		repositoryUrls.add(
				urlPrefix + repository.getUrl() 
				+ "@id=" + repository.getName() 
				+ "@checksum=ignore"
				+ (repository.isSnapshotsAllowed()?"@snapshots":"")
			);
		
		// check if 'updates' repository is defined
		repository = artifactService.getRepository(ArtifactRepository.REPO_NAME_UPDATES);
		if (!repository.isHealthy() && repository.isEnabled()) {
			// TODO create own exceptions 
			throw new InitializerException(this
					, String.format("Repository [{}] is not healthy, but enabled", repository.getName())
					, "Please check the configuration", null);
		}
		if (!repository.isEnabled())
			log.warn("Repository [{}] is not enabled, make sure it's not done by mistake", ArtifactRepository.REPO_NAME_UPDATES);
		else
			repositoryUrls.add(
					urlPrefix + repository.getUrl() 
					+ "@id=" + repository.getName()
					+ (repository.isSnapshotsAllowed()?"@snapshots":"")
				);
		
		String repositoryUrlsResult = repositoryUrls.stream().collect(Collectors.joining(", "));
		
		ServiceReference<ConfigRepository> ref1 = this.bundleContext.getServiceReference(ConfigRepository.class);
		this.configRepository = this.bundleContext.getService(ref1);

		try {
			
			TypedProperties properties = this.configRepository.getConfig(MVN_PID);
			
			properties.put(PROP_ENTAXY_REPO_LIST, repositoryUrlsResult);
			this.configRepository.update(MVN_PID, properties);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidSyntaxException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	@Override
	public void reinit() throws InitializerException {
		// TODO Auto-generated method stub

	}

}
