
package com.b2international.snowowl.test.commons;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.File;

import org.junit.rules.ExternalResource;

import com.b2international.commons.ConsoleProgressMonitor;
import com.b2international.commons.platform.PlatformUtil;
import com.b2international.snowowl.core.ApplicationContext;
import com.b2international.snowowl.core.api.IBranchPath;
import com.b2international.snowowl.core.branch.Branch;
import com.b2international.snowowl.datastore.BranchPathUtils;
import com.b2international.snowowl.datastore.CodeSystems;
import com.b2international.snowowl.datastore.request.RepositoryRequests;
import com.b2international.snowowl.eventbus.IEventBus;
import com.b2international.snowowl.snomed.common.ContentSubType;
import com.b2international.snowowl.snomed.common.SnomedTerminologyComponentConstants;
import com.b2international.snowowl.snomed.core.domain.Rf2ReleaseType;
import com.b2international.snowowl.snomed.datastore.SnomedDatastoreActivator;
import com.b2international.snowowl.snomed.importer.rf2.util.ImportUtil;
import com.b2international.snowowl.terminologyregistry.core.request.CodeSystemRequests;

/**
 * JUnit test rule to import SNOMED CT content during automated tests.
 * 
 * @since 3.6
 */
public class SnomedContentRule extends ExternalResource {

	private final File importArchive;
	private final Rf2ReleaseType contentType;
	private final String codeSystemShortName;
	private final String codeSystemBranchPath;

	public SnomedContentRule(final String codeSystemShortName, final String branchPath, final String importArchivePath, final Rf2ReleaseType contentType) {
		this(codeSystemShortName, branchPath, SnomedContentRule.class, importArchivePath, contentType);
	}
	
	public SnomedContentRule(final String codeSystemShortName, final String branchPath, final Class<?> relativeClass, final String importArchivePath, final Rf2ReleaseType contentType) {
		this.codeSystemShortName = checkNotNull(codeSystemShortName, "codeSystem");
		this.codeSystemBranchPath = checkNotNull(branchPath, "branchPath");
		this.contentType = checkNotNull(contentType, "contentType");
		this.importArchive = PlatformUtil.toAbsolutePathBundleEntry(relativeClass, importArchivePath).toFile();
	}

	@Override
	protected void before() throws Throwable {
		createBranch();
		createCodeSystemIfNotExist();
		new ImportUtil().doImport(codeSystemShortName, "info@b2international.com", getContentSubType(contentType), codeSystemBranchPath, importArchive, true, new ConsoleProgressMonitor());
	}
	
	private static ContentSubType getContentSubType(Rf2ReleaseType contentType) {
		switch (contentType) {
		case DELTA: return ContentSubType.DELTA;
		case SNAPSHOT: return ContentSubType.SNAPSHOT;
		case FULL: return ContentSubType.FULL;
		}
		return null;
	}

	private void createBranch() {
		if (!IBranchPath.MAIN_BRANCH.equals(codeSystemBranchPath)) {
			final IBranchPath csPath = BranchPathUtils.createPath(codeSystemBranchPath);
			RepositoryRequests.branching().prepareCreate()
				.setParent(csPath.getParentPath())
				.setName(csPath.lastSegment())
				.build(SnomedDatastoreActivator.REPOSITORY_UUID)
				.execute(getBus())
				.getSync()
				.path();
		}
	}

	private void createCodeSystemIfNotExist() {
		if (!SnomedTerminologyComponentConstants.SNOMED_SHORT_NAME.equals(codeSystemShortName)) {
			final IEventBus eventBus = getBus();
			
			CodeSystems codeSystems = CodeSystemRequests.prepareSearchCodeSystem()
					.setLimit(0)
					.filterById(codeSystemShortName)
					.build(SnomedDatastoreActivator.REPOSITORY_UUID)
					.execute(eventBus)
					.getSync();
			
			if (codeSystems.getTotal() < 1) {
				CodeSystemRequests.prepareNewCodeSystem()
					.setBranchPath(codeSystemBranchPath)
					.setCitation("citation")
					.setExtensionOf(SnomedTerminologyComponentConstants.SNOMED_SHORT_NAME)
					.setIconPath("iconPath")
					.setLanguage("language")
					.setLink("organizationLink")
					.setName("Extension " + codeSystemShortName)
					.setOid("oid:"+codeSystemShortName)
					.setRepositoryUuid(SnomedDatastoreActivator.REPOSITORY_UUID)
					.setShortName(codeSystemShortName)
					.setTerminologyId(SnomedTerminologyComponentConstants.TERMINOLOGY_ID)
					.build(SnomedDatastoreActivator.REPOSITORY_UUID, Branch.MAIN_PATH, "info@b2international.com", String.format("Create code system %s", codeSystemShortName))
					.execute(eventBus)
					.getSync();
			}
		}
	}
	
	private static IEventBus getBus() {
		return ApplicationContext.getServiceForClass(IEventBus.class);
	}
}
