package org.codiki.posts;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codiki.core.entities.dto.PostDTO;
import org.codiki.core.entities.persistence.Post;
import org.codiki.core.entities.persistence.User;
import org.codiki.core.repositories.PostRepository;
import org.codiki.core.security.TokenService;
import org.codiki.core.services.ParserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/posts")
public class PostController {

	private static final int LIMIT_POSTS_HOME = 20;
	
	@Autowired
	private ParserService parserService;
	
	@Autowired
	private PostRepository postRepository;
	
	@Autowired
	private TokenService tokenService;
	
	@Autowired
	private PostService postService;
	
	@GetMapping
	public List<PostDTO> getAll() {
		return StreamSupport.stream(postRepository.findAll().spliterator(), false)
				.map(PostDTO::new).collect(Collectors.toList());
	}
	
	@GetMapping("/{postKey}")
	public PostDTO getByKey(@PathVariable("postKey") final String pPostKey, 
			final HttpServletResponse response) {
		final PostDTO result = getByKeyAndSource(pPostKey, response);
		if(result != null) {
			result.setText(parserService.parse(result.getText()));
		}
		return result;
	}
	
	@GetMapping("/{postKey}/source")
	public PostDTO getByKeyAndSource(@PathVariable("postKey")final String pPostKey,
			final HttpServletResponse response) {
		PostDTO result = null;
		
		final Optional<Post> post = postRepository.getByKey(pPostKey);
		if(post.isPresent()) {
			result = new PostDTO(post.get());
		} else {
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
		}
		
		return result;
	}
	
	@GetMapping("/last")
	public List<PostDTO> getLast() {
		return postRepository.getLast(LIMIT_POSTS_HOME).stream()
				.map(PostDTO::new).collect(Collectors.toList());
	}
	
	@GetMapping("/search/{searchCriteria}")
	public List<PostDTO> search(@PathVariable("searchCriteria") final String pSearchCriteria) {
		return postService.search(pSearchCriteria);
	}
	
	@GetMapping("/byCategory/{categoryId}")
	public List<PostDTO> getByCategory(@PathVariable("categoryId") final Long pCategoryId) {
		return postRepository.getByCategoryId(pCategoryId).stream()
				.map(PostDTO::new).collect(Collectors.toList());
	}
	
	@GetMapping("/myPosts")
	public List<PostDTO> getMyPosts(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
		List<PostDTO> result = new LinkedList<>();
		
		final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
		if(connectedUser.isPresent()) {
			result = postRepository.getByCreator(connectedUser.get().getId())
					.stream().map(PostDTO::new).collect(Collectors.toList());
		} else {
			pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
		}
		
		return result;
	}
	
	@PostMapping("/preview")
	public PostDTO preview(@RequestBody final PostDTO pPost) {
		final PostDTO result = new PostDTO();
		
		result.setTitle(pPost.getTitle());
		result.setImage(pPost.getImage() == null || "".equals(pPost.getImage())
				? "https://news-cdn.softpedia.com/images/news2/this-is-the-default-wallpaper-of-the-gnome-3-20-desktop-environment-500743-2.jpg"
				: pPost.getImage());
		result.setDescription(pPost.getDescription());
		result.setText(parserService.parse(pPost.getText()));
		
		return result;
	}
	
	@PostMapping("/")
	public PostDTO insert(@RequestBody final PostDTO pPost, final HttpServletRequest pRequest,
			final HttpServletResponse pResponse) {
		PostDTO result = null;
		
		Optional<Post> postCreated = postService.insert(pPost, pRequest, pResponse);
		
		if(postCreated.isPresent()) {
			result = new PostDTO(postCreated.get());
		}
		
		return result;
	}
	
	@PutMapping("/")
	public void update(@RequestBody final PostDTO pPost, final HttpServletRequest pRequest,
			final HttpServletResponse pResponse) throws IOException {
		postService.update(pPost, pRequest, pResponse);
	}
	
	@DeleteMapping("/{postKey}")
	public void delete(@PathVariable("postKey") final String pPostKey,
			final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
		postService.delete(pPostKey, pRequest, pResponse);
	}
}
