package consulo.webService.storage;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.intellij.openapi.util.Pair;
import consulo.externalStorage.storage.DataCompressor;
import consulo.webService.auth.oauth2.domain.OAuth2AuthenticationAccessToken;
import consulo.webService.auth.oauth2.mongo.OAuth2AccessTokenRepository;
import consulo.webService.storage.bean.PushFileBeanRequest;
import consulo.webService.storage.bean.PushFileBeanResponse;
import consulo.webService.storage.mongo.MongoStorageFile;
import consulo.webService.storage.mongo.MongoStorageFileRepository;
import consulo.webService.storage.mongo.MongoStorageFileUpdateBy;

/**
 * @author VISTALL
 * @since 12-Feb-17
 */
@RestController
public class StorageRestController
{
	@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
	private static class NotAuthorizedException extends RuntimeException
	{
	}

	@Autowired
	private MongoStorageFileRepository myStorageFileRepository;

	@Autowired
	private OAuth2AccessTokenRepository myOAuth2AccessTokenRepository;

//	@RequestMapping(value = "/api/storage/getAll", method = RequestMethod.GET)
//	public ResponseEntity<?> getAll(@RequestHeader("Authorization") String authorization) throws IOException
//	{
//		OAuth2AuthenticationAccessToken token = myOAuth2AccessTokenRepository.findByTokenId(authorization);
//		if(token == null)
//		{
//			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
//		}
//
//		List<MongoStorageFile> list = myStorageFileRepository.findByEmail(token.getUserName());
//		if(list.isEmpty())
//		{
//			return ResponseEntity.noContent().build();
//		}
//
//		BufferExposingByteArrayOutputStream arrayOutputStream = new BufferExposingByteArrayOutputStream();
//		try (DataOutputStream stream = new DataOutputStream(arrayOutputStream))
//		{
//			stream.writeByte(0x01); // version
//
//			stream.writeShort(list.size());
//			for(MongoStorageFile storageFile : list)
//			{
//				stream.writeInt(storageFile.getModCount());
//				stream.writeUTF(storageFile.getFilePath());
//				byte[] data = storageFile.getData();
//				stream.writeShort(data.length);
//				stream.write(data);
//			}
//		}
//
//		return ResponseEntity.ok(new ByteArrayResource(arrayOutputStream.toByteArray()));
//	}

	@RequestMapping(value = "/api/storage/getFile", method = RequestMethod.GET)
	public ResponseEntity<?> getFile(@RequestParam("filePath") String filePath, @RequestParam("modCount") int modCount, @RequestHeader("Authorization") String authorization)
	{
		OAuth2AuthenticationAccessToken token = myOAuth2AccessTokenRepository.findByTokenId(authorization);
		if(token == null)
		{
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
		}

		MongoStorageFile storageFile = myStorageFileRepository.findByEmailAndFilePath(token.getUserName(), filePath);
		if(storageFile == null)
		{
			return ResponseEntity.notFound().build();
		}

		if(storageFile.getModCount() == modCount)
		{
			return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
		}

		try
		{
			byte[] data = storageFile.getData();
			byte[] compressedData = DataCompressor.compress(data, data.length, storageFile.getModCount());
			return ResponseEntity.ok(new ByteArrayResource(compressedData));
		}
		catch(IOException e)
		{
			throw new RuntimeException(e);
		}
	}

	@RequestMapping(value = "/api/storage/pushFile", method = RequestMethod.POST)
	public PushFileBeanResponse pushFile(@RequestBody(required = true) PushFileBeanRequest data, @RequestHeader("Authorization") String authorization) throws Exception
	{
		OAuth2AuthenticationAccessToken token = myOAuth2AccessTokenRepository.findByTokenId(authorization);
		if(token == null)
		{
			throw new NotAuthorizedException();
		}

		String filePath = data.getFilePath();

		MongoStorageFile prevFile = myStorageFileRepository.findByEmailAndFilePath(token.getUserName(), filePath);

		int count;
		MongoStorageFile file = prevFile == null ? new MongoStorageFile() : prevFile;

		if(prevFile != null)
		{
			file.setModCount(count = (file.getModCount() + 1));
		}
		else
		{
			file.setFilePath(filePath);
			file.setEmail(token.getUserName());
			file.setModCount(count = 1);
		}

		MongoStorageFileUpdateBy by = new MongoStorageFileUpdateBy();
		by.setTime(System.currentTimeMillis());
		data.copyTo(by);

		file.setUpdateBy(by);

		String bytes = data.getBytes();

		Pair<byte[], Integer> uncompress = DataCompressor.uncompress(new ByteArrayInputStream(Base64.getDecoder().decode(bytes)));

		file.setData(uncompress.getFirst());

		myStorageFileRepository.save(file);

		return new PushFileBeanResponse(count);
	}
}

@@ -3960,24 +3960,719 @@
 e);%0A%09%09%7D%0A%09%7D%0A%0A
+%09@RequestMapping(value = %22/api/storage/deleteFile%22, method = RequestMethod.GET)%0A%09public ResponseEntity%3C?%3E deleteFile(@RequestParam(%22filePath%22) String filePath, @RequestHeader(%22Authorization%22) String authorization)%0A%09%7B%0A%09%09OAuth2AuthenticationAccessToken token = myOAuth2AccessTokenRepository.findByTokenId(authorization);%0A%09%09if(token == null)%0A%09%09%7B%0A%09%09%09return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();%0A%09%09%7D%0A%0A%09%09MongoStorageFile storageFile = myStorageFileRepository.findByEmailAndFilePath(token.getUserName(), filePath);%0A%09%09if(storageFile == null)%0A%09%09%7B%0A%09%09%09return ResponseEntity.notFound().build();%0A%09%09%7D%0A%0A%09%09myStorageFileRepository.delete(storageFile);%0A%09%09return ResponseEntity.ok().build();%0A%09%7D%0A%0A
 %09@RequestMap

add support for delete file