package ua.be.wee.service;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;

@Service
public class FileStorageServiceImpl implements FileStorageService {
	private final Path root = Paths.get("");

	public String storageServiceURL;
	
	
	@Autowired
	private Environment env;

	@Override
	public void init() {
		try {
			//Files.createDirectories(root);
			storageServiceURL = env.getProperty("storageURL");
		} catch (Exception e) {
			throw new RuntimeException("Could not get property storageURL from application.properties file!");
		}
	}

	@Override
	public void save(InputStream file, String filename) {
		try {
			if (storageServiceURL == null) {
				init();
			}
			//Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()));
			String url = "";
			switch (filename.substring(filename.lastIndexOf('.'))) {
			case ".xopp":
				url = storageServiceURL + "/files/xopp/"+filename;				
				break;
			case ".csv":
				url = storageServiceURL +"/files/csv/"+filename;				
				break;
			case ".drawio":
				url = storageServiceURL + "/files/drawio/"+filename;				
				break;
			default:
				url = storageServiceURL + "/files/file/"+filename; 
				break;
			}
			
			CloseableHttpClient httpclient = HttpClients.createDefault();
			
			HttpPut httpPut = new HttpPut(url);
			
			
			// specify the PUT body to send to the server as part of the request
			//httpPut.setEntity(new StringEntity(file.getInputStream().toString()));

			httpPut.setEntity(new InputStreamEntity(file));
			
			
			HttpResponse response = httpclient.execute(httpPut);

			String responseBody = new BasicResponseHandler().handleResponse(response);	
			
			
			httpclient.close();
			
		} catch (Exception e) {
			if (e instanceof FileAlreadyExistsException) {
				throw new RuntimeException("A file of that name already exists.");
			}

			throw new RuntimeException(e.getMessage());
		}
	}

	@Override
	public String load(String filename) {
		try {
			if (storageServiceURL == null) {
				init();
			}
			//Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()));
			String url = "";
			switch (filename.substring(filename.lastIndexOf('.'))) {
			case ".xopp":
				url = storageServiceURL + "/files/xopp/"+filename;				
				break;
			case ".csv":
				url = storageServiceURL +"/files/csv/"+filename;				
				break;
			case ".drawio":
				url = storageServiceURL + "/files/drawio/"+filename;				
				break;
			default:
				url = storageServiceURL + "/files/file/"+filename; 
				break;
			}
			
			CloseableHttpClient httpclient = HttpClients.createDefault();
			
			HttpGet httpGet = new HttpGet(url);
			
			
			// specify the PUT body to send to the server as part of the request
			//httpPut.setEntity(new StringEntity(file.getInputStream().toString()));

			
			
			HttpResponse response = httpclient.execute(httpGet);

			String responseBody = new BasicResponseHandler().handleResponse(response);
			
			httpclient.close();
			
			return responseBody;
			
			
			
		} catch (MalformedURLException e) {
			throw new RuntimeException("Error: " + e.getMessage());
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public boolean delete(String filename) {
		try {
			Path file = root.resolve(filename);
			return Files.deleteIfExists(file);
		} catch (IOException e) {
			throw new RuntimeException("Error: " + e.getMessage());
		}
	}

	@Override
	public void deleteAll() {
		FileSystemUtils.deleteRecursively(root.toFile());
	}

	@Override
	public Stream<Path> loadAll() {
		try {
			return Files.walk(this.root, 1).filter(path -> !path.equals(this.root)).map(this.root::relativize);
		} catch (IOException e) {
			throw new RuntimeException("Could not load the files!");
		}
	}

	@Override
	public void setStorageURL(String url) {
		storageServiceURL = url;
		
	}

	@Override
	public String getURL(String filename) {
		
			if (storageServiceURL == null) {
				init();
			}
			//Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()));
			String url = "";
			switch (filename.substring(filename.lastIndexOf('.'))) {
			case ".xopp":
				url = storageServiceURL + "/files/xopp/"+filename;				
				break;
			case ".csv":
				url = storageServiceURL +"/files/csv/"+filename;				
				break;
			case ".drawio":
				url = storageServiceURL + "/files/drawio/"+filename;				
				break;
			default:
				url = storageServiceURL + "/files/file/"+filename; 
				break;
			}
		return url;
	}
}
