/*
 * Copyright 2020 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.core.request.io;

import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

import javax.validation.constraints.NotNull;

import org.eclipse.core.runtime.IProgressMonitor;

import com.b2international.commons.exceptions.ApiException;
import com.b2international.snowowl.core.attachments.Attachment;
import com.b2international.snowowl.core.attachments.AttachmentRegistry;
import com.b2international.snowowl.core.attachments.InternalAttachmentRegistry;
import com.b2international.snowowl.core.authorization.BranchAccessControl;
import com.b2international.snowowl.core.domain.TransactionContext;
import com.b2international.snowowl.core.identity.Permission;
import com.b2international.snowowl.core.internal.locks.DatastoreLockContextDescriptions;
import com.b2international.snowowl.core.request.LockRequest;
import com.b2international.snowowl.core.uri.ComponentURI;
import com.google.common.collect.Sets;

/**
 * @since 7.12
 */
public abstract class ImportRequest extends LockRequest<TransactionContext, ImportResponse> implements BranchAccessControl {
	
	private static final long serialVersionUID = 1L;
	
	@NotNull
	private Attachment attachment;
	
	public ImportRequest() {
		super(DatastoreLockContextDescriptions.IMPORT);
	}
	
	public ImportRequest(String lockContext, String parentLockContext) {
		super(lockContext, parentLockContext);
	}
	
	final void setAttachment(Attachment attachment) {
		this.attachment = attachment;
	}
	
	protected Attachment attachment() {
		return attachment;
	}
	
	@Override
	public final ImportResponse doExecute(TransactionContext context) {
		context.log().info("Importing components from source file '%s'.", this.attachment.getFileName());
		try {
			InternalAttachmentRegistry iar = (InternalAttachmentRegistry) context.service(AttachmentRegistry.class);
			File attachment = iar.getAttachment(this.attachment.getAttachmentId());
			
			ImportDefectAcceptor defectsAcceptor = new ImportDefectAcceptor(this.attachment.getFileName());
			doValidate(context, attachment, defectsAcceptor, context.service(IProgressMonitor.class));
			
			final ImportResponse validationResponse = ImportResponse.defects(defectsAcceptor.getDefects());
			if (!validationResponse.getErrors().isEmpty()) {
				return validationResponse;
			} else {
				final Set<ComponentURI> visitedComponents = Sets.newHashSet();
				doImport(context, attachment, visitedComponents::add, context.service(IProgressMonitor.class));
				return ImportResponse.success(visitedComponents, validationResponse.getDefects());
			}
			
		} catch (ApiException e) {
			throw e;
		} catch (Exception e) {
			String error = "Unexpected error happened during the import of the source file: " + attachment.getFileName();
			context.log().error(error, e);
			return ImportResponse.error(error);
		} finally {
			context.log().info("Finished importing components from source file '%s'.", this.attachment.getFileName());
		}
	}

//	/**
//	 * Logs the import activity with the given message.
//	 * 
//	 * @param message the message to be logged.
//	 */
//	protected void logImportActivity(final String message) {
//		LogUtils.logImportActivity(context.log(), context.author(), context.path(), message);
//	}
//	
//	/**
//	 * Logs the import warning with the given message.
//	 * 
//	 * @param message the message to be logged.
//	 */
//	protected void logImportWarning(final String message) {
//		LogUtils.logImportWarning(context.log(), context.author(), context.path(), message);
//	}
	
	/**
	 * Subclasses optionally provider validation functionality to verify the integrity of the attachment before proceeding to the actual import in {@link #doImport(File, IProgressMonitor)}.
	 * @param context - the context to run the validation on
	 * @param attachment - the file attachment to validate
	 * @param defectsAcceptor - the acceptor that collects {@link ImportDefect}s through a few helper methods
	 * @param monitor - the monitor that can be used to track progress
	 * @return a {@link List} of {@link ImportDefect} instances that can aid the user pinpoint and resolve the errors/issues
	 * @throws Exception
	 */
	protected void doValidate(TransactionContext context, File attachment, ImportDefectAcceptor defectsAcceptor, IProgressMonitor monitor) throws Exception {
	}

	/**
	 * Performs the import from the given file attachment.
	 * 
	 * @param context - the context that can be used to commit changes
	 * @param attachment - the attachment file to import
	 * @param visitor - visitor that accepts visited component URIs
	 * @param monitor - the monitor that can be used to track progress
	 * @return
	 * @throws Exception
	 */
	protected abstract void doImport(TransactionContext context, File attachment, Consumer<ComponentURI> visitor, IProgressMonitor monitor) throws Exception;
	
	@Override
	public String getOperation() {
		return Permission.OPERATION_IMPORT;
	}
	
}

@@ -695,31 +695,8 @@
 le;%0A
-import java.util.List;%0A
 impo
@@ -3586,567 +3586,8 @@
 %09%7D%0A%0A
-//%09/**%0A//%09 * Logs the import activity with the given message.%0A//%09 * %0A//%09 * @param message the message to be logged.%0A//%09 */%0A//%09protected void logImportActivity(final String message) %7B%0A//%09%09LogUtils.logImportActivity(context.log(), context.author(), context.path(), message);%0A//%09%7D%0A//%09%0A//%09/**%0A//%09 * Logs the import warning with the given message.%0A//%09 * %0A//%09 * @param message the message to be logged.%0A//%09 */%0A//%09protected void logImportWarning(final String message) %7B%0A//%09%09LogUtils.logImportWarning(context.log(), context.author(), context.path(), message);%0A//%09%7D%0A%09%0A
 %09/**
@@ -3774,16 +3774,21 @@
 itor)%7D.%0A
+%09 * %0A
 %09 * @par
@@ -4072,130 +4072,8 @@
 ess%0A
-%09 * @return a %7B@link List%7D of %7B@link ImportDefect%7D instances that can aid the user pinpoint and resolve the errors/issues%0A
 %09 * 
@@ -4507,16 +4507,16 @@
 nt URIs%0A
+
 %09 * @par
@@ -4579,20 +4579,8 @@
 ess%0A
-%09 * @return%0A
 %09 * 

clean up in ImportRequest