/*
 * Copyright 2018 B2i Healthcare Pte Ltd, http://b2i.sg
 * 
 * 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.
 */
package com.b2international.snowowl.fhir.core.provider;

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

import com.b2international.commons.exceptions.BadRequestException;
import com.b2international.commons.extension.ClassPathScanner;
import com.b2international.commons.http.ExtendedLocale;
import com.b2international.snowowl.eventbus.IEventBus;
import com.b2international.snowowl.fhir.core.LogicalId;
import com.b2international.snowowl.fhir.core.codesystems.OperationOutcomeCode;
import com.b2international.snowowl.fhir.core.model.conceptmap.ConceptMap;
import com.b2international.snowowl.fhir.core.model.conceptmap.Match;
import com.b2international.snowowl.fhir.core.model.conceptmap.TranslateRequest;
import com.b2international.snowowl.fhir.core.model.conceptmap.TranslateResult;
import com.google.common.collect.ImmutableList;

/**
 * Extension point interface for concept map specific FHIR API support. 
 * 
 * @since 6.9
 */
public interface IConceptMapApiProvider extends IFhirApiProvider {

	/**
	 * Registry that reads and instantiates FHIR API supporting services registered by the actual terminology plug-ins.
	 * 
	 * @since 6.9
	 */
	enum Registry {
		
		INSTANCE;
		
		private final Collection<IConceptMapApiProvider.Factory> providers;
		
		private Registry() {
			this.providers = ImmutableList.copyOf(ClassPathScanner.INSTANCE.getComponentsByInterface(IConceptMapApiProvider.Factory.class));
		}
		
		public static Collection<IConceptMapApiProvider> getProviders(IEventBus bus, List<ExtendedLocale> locales) {
			return INSTANCE.providers.stream().map(factory -> factory.create(bus, locales)).collect(Collectors.toUnmodifiableList());
		}
		
		/**
		 * Returns the matching {@link IConceptMapApiProvider} for the given path (repository:branchPath).
		 * @param bus
		 * @param locales
		 * @param logical code system path (e.g.icd10Store:20140101)
		 * @return FHIR concept map provider
		 * @throws com.b2international.snowowl.fhir.core.exceptions.BadRequestException - if provider is not found with the given path
		 */
		public static IConceptMapApiProvider getConceptMapProvider(IEventBus bus, List<ExtendedLocale> locales, LogicalId logicalId) {
			return getProviders(bus, locales).stream()
				.filter(provider -> provider.isSupported(logicalId))
				.findFirst()
				.orElseThrow(() -> new BadRequestException("Did not find FHIR module for managing concept map: " + logicalId, OperationOutcomeCode.MSG_NO_MODULE, "system=" + logicalId));
		}
		
		/**
		 * Returns the matching {@link IConceptMapApiProvider} for the given URI.
		 * @param bus
		 * @param locales
		 * @param uriValue
		 * @return FHIR value set provider
		 */
		public static IConceptMapApiProvider getConceptMapProvider(IEventBus bus, List<ExtendedLocale> locales, String uriValue) {
			return getProviders(bus, locales).stream()
				.filter(provider -> provider.isSupported(uriValue))
				.findFirst()
				.orElseThrow(() -> new BadRequestException("Did not find FHIR module for managing concept map: " + uriValue, OperationOutcomeCode.MSG_NO_MODULE, "system=" + uriValue));
		}
	}
	
	/**
	 * @since 7.2
	 */
	interface Factory {
		IConceptMapApiProvider create(IEventBus bus, List<ExtendedLocale> locales);
	}
	
	/**
	 * Returns the concept maps supported by this provider.
	 * @return collection of concept maps supported
	 */
	Collection<ConceptMap> getConceptMaps();

	/**
	 * Returns the concept map for the passed in logical id (repositoryId:branchPath/conceptMapId)
	 * @param logicalId
	 * @return {@link ConceptMap}
	 * @throws BadRequestException if the concept map is not supported by this provider
	 */
	ConceptMap getConceptMap(LogicalId logicalId);

	/**
	 * Returns a the collection of mapping matches as a translate result from a given Concept Map
	 * @param {@link TranslateRequest}
	 * @param logicalId logical if of the {@link ConceptMap}
	 * @return {@link TranslateResult}
	 */
	TranslateResult translate(LogicalId logicalId, TranslateRequest translateRequest);

	/**
	 * Returns a collection of mapping matches for the given translate request
	 * These mappings can be fetched from any concept map in the system.
	 * 
	 * @param {@link TranslateRequest}
	 * @return collection of translate matches
	 */
	Collection<Match> translate(TranslateRequest translateRequest);
	
}

@@ -2478,16 +2478,18 @@
  logical
+Id
  code sy
@@ -4421,44 +4421,8 @@
 Map%0A
-%09 * @param %7B@link TranslateRequest%7D%0A
 %09 * 
@@ -4429,32 +4429,34 @@
 @param logicalId
+ -
  logical if of t
@@ -4473,24 +4473,79 @@
 ConceptMap%7D%0A
+%09 * @param translateRequest - %7B@link TranslateRequest%7D%0A
 %09 * @return 
@@ -4540,24 +4540,26 @@
 %09 * @return 
+a 
 %7B@link Trans
@@ -4569,16 +4569,25 @@
 eResult%7D
+ instance
 %0A%09 */%0A%09T
@@ -4836,16 +4836,33 @@
  @param 
+translateRequest 
 %7B@link T
@@ -4914,22 +4914,36 @@
 anslate 
-matche
+%7B@link Match%7D object
 s%0A%09 */%0A%09

fix spurious javadocs