/*
 * Copyright 2011-2015 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.snomed.api.rest;

import static com.b2international.snowowl.snomed.api.rest.domain.SnomedImportStatus.getImportStatus;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.b2international.snowowl.snomed.api.ISnomedRf2ImportService;
import com.b2international.snowowl.snomed.api.domain.ISnomedImportConfiguration;
import com.b2international.snowowl.snomed.api.impl.domain.SnomedImportConfiguration;
import com.b2international.snowowl.snomed.api.rest.domain.SnomedImportDetails;
import com.b2international.snowowl.snomed.api.rest.domain.SnomedImportRestConfiguration;
import com.b2international.snowowl.snomed.api.rest.util.Responses;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;

/**
 * @since 1.0
 */
@RestController
@RequestMapping(
		value="/imports",
		produces={ AbstractRestService.V1_MEDIA_TYPE })
@Api(value="SNOMED CT Import")
public class SnomedImportRestService extends AbstractSnomedRestService {

	@Autowired
	private ISnomedRf2ImportService delegate; 
	
	@ApiOperation(
			value="Import SNOMED CT content", 
			notes="Configures processes to import RF2 based archives. The configured process will wait until the archive actually uploaded via the <em>/archive</em> endpoint. "
					+ "The actual import process will start after the file upload completed.")
	@ApiResponses({
		@ApiResponse(code = 201, message = "Created"),
		@ApiResponse(code = 404, message = "Code system version not found"),
		@ApiResponse(code = 404, message = "Task not found"),
	})
	@RequestMapping(method=RequestMethod.POST,
		consumes={ AbstractRestService.V1_MEDIA_TYPE, MediaType.APPLICATION_JSON_VALUE })
	@ResponseStatus(HttpStatus.CREATED)
	public ResponseEntity<Void> create(
			@ApiParam(value="Import parameters")
			@RequestBody 
			final SnomedImportRestConfiguration importConfiguration) {

		final UUID importId = delegate.create(convertToConfiguration(importConfiguration));
		return Responses.created(linkTo(methodOn(SnomedImportRestService.class).getImportDetails(importId)).toUri()).build();
	}

	@ApiOperation(
			value="Retrieve import run details", 
			notes="Returns the specified import run's configuration and status.")
	@ApiResponses({
		@ApiResponse(code = 200, message = "OK"),
		@ApiResponse(code = 404, message = "Code system version or import not found"),
	})
	@RequestMapping(value="/{importId}", method=RequestMethod.GET)
	public SnomedImportDetails getImportDetails(
			@ApiParam(value="The import identifier")
			@PathVariable(value="importId") 
			final UUID importId) {

		return convertToDetails(importId, delegate.getImportDetails(importId));
	}
	
	@ApiOperation(
			value="Delete import run", 
			notes="Removes a pending or finished import configuration from the server.")
	@ApiResponses({
		@ApiResponse(code = 204, message = "Delete successful"),
		@ApiResponse(code = 404, message = "Code system version or import not found"),
	})
	@RequestMapping(value="/{importId}", method=RequestMethod.DELETE)
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void deleteImportDetails(
			@ApiParam(value="The import identifier")
			@PathVariable(value="importId") 
			final UUID importId) {
		
		delegate.deleteImportDetails(importId);
	}
	
	@ApiOperation(
			value="Upload archive file and start the import", 
			notes="Removes a pending or finished import configuration from the server.")
	@ApiResponses({
		@ApiResponse(code = 204, message = "No content"),
		@ApiResponse(code = 404, message = "Code system version or import not found"),
	})
	@RequestMapping(value="/{importId}/archive", 
		method=RequestMethod.POST, 
		consumes={ MediaType.MULTIPART_FORM_DATA_VALUE })
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void startImport(
			@ApiParam(value="The import identifier")
			@PathVariable(value="importId") 
			final UUID importId,
			
			@ApiParam(value="RF2 import archive")
			@RequestPart("file") 
			final MultipartFile file) {
		
		checkNotNull(file, "SNOMED CT RF2 release archive should be specified.");
		
		try (final InputStream is = file.getInputStream()) {
			delegate.startImport(importId, is);
		} catch (final IOException e) {
			throw new RuntimeException("Error while reading SNOMED CT RF2 release archive content.");
		}
	}
	
	private SnomedImportDetails convertToDetails(final UUID importId, 
			final ISnomedImportConfiguration configuration) {
		
		final SnomedImportDetails details = new SnomedImportDetails();
		details.setCompletionDate(configuration.getCompletionDate());
		details.setCreateVersions(configuration.shouldCreateVersion());
		details.setId(importId);
		details.setLanguageRefSetId(configuration.getLanguageRefSetId());
		details.setStartDate(configuration.getStartDate());
		details.setStatus(getImportStatus(configuration.getStatus()));
		details.setTaskId(configuration.getTaskId());
		details.setType(configuration.getRf2ReleaseType());
		details.setVersion(configuration.getVersion());
		return details;
	}
	
	private ISnomedImportConfiguration convertToConfiguration(final SnomedImportRestConfiguration configuration) {
		
		return new SnomedImportConfiguration(
				configuration.getType(), 
				configuration.getVersion(),
				configuration.getTaskId(),
				configuration.getLanguageRefSetId(), 
				configuration.getCreateVersions());
	}
	
}

@@ -3093,16 +3093,148 @@
 mpleted.
+ Note: unpublished components (with no value entered in the 'effectiveTime' column) are %22%0A%09%09%09%09%09+ %22only allowed in DELTA import mode.
 %22)%0D%0A%09@Ap

Add note to SnomedImportRestService