package com.drumonii.loltrollbuild.rest;

import com.drumonii.loltrollbuild.model.Build;
import com.drumonii.loltrollbuild.repository.*;
import com.drumonii.loltrollbuild.rest.status.BadRequestException;
import com.drumonii.loltrollbuild.rest.status.ResourceNotFoundException;
import com.drumonii.loltrollbuild.rest.view.ApiViews;
import com.fasterxml.jackson.annotation.JsonView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.validation.Valid;
import java.util.Optional;

/**
 * Repository REST controller for {@link Build}s.
 */
@RestController
@RequestMapping("${api.base-path}/builds")
public class BuildsRestController {

	static final int PAGE_SIZE = 20;

	@Autowired
	private BuildsRepository buildsRepository;

	@Autowired
	private ChampionsRepository championsRepository;

	@Autowired
	private ItemsRepository itemsRepository;

	@Autowired
	private SummonerSpellsRepository summonerSpellsRepository;

	@Autowired
	private MapsRepository mapsRepository;

	@Autowired
	@Qualifier("mvcValidator")
	private Validator validator;

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setValidator(validator);
	}

	/**
	 * Gets a {@link Page} of {@link Build}s from the pagination and search parameters.
	 *
	 * @param pageable the {@link Pageable}
	 * @param build the search {@link Build} to define as the QBE
	 * @return the {@link Page} of {@link Build}s
	 */
	@GetMapping
	public Page<Build> getBuilds(
			@PageableDefault(size = PAGE_SIZE, sort = "id", direction = Direction.DESC) Pageable pageable, Build build) {
		ExampleMatcher exampleMatcher = ExampleMatcher.matching()
				.withIgnorePaths("id")
				.withIgnoreNullValues();
		Example<Build> example = Example.of(build, exampleMatcher);
		return buildsRepository.findAll(example, pageable);
	}

	/**
	 * Gets a {@link Build} by its ID. If not found, returns a 404, or if some of its attributes no longer exist a 400,
	 * otherwise a 200.
	 *
	 * @param id the ID to lookup the {@link Build}
	 * @return the {@link Build}
	 */
	@JsonView({ ApiViews.LtbApi.class })
	@GetMapping(path = "/{id}")
	public Build getBuild(@PathVariable int id) {
		Optional<Build> optionalBuild = buildsRepository.findById(id);
		if (!optionalBuild.isPresent()) {
			throw new ResourceNotFoundException("Unable to find a Build with Id: " + id);
		}
		Build build = optionalBuild.get();
		build.setChampion(championsRepository.findById(build.getChampionId()).orElse(null));
		build.setItem1(itemsRepository.findById(build.getItem1Id()).orElse(null));
		build.setItem2(itemsRepository.findById(build.getItem2Id()).orElse(null));
		build.setItem3(itemsRepository.findById(build.getItem3Id()).orElse(null));
		build.setItem4(itemsRepository.findById(build.getItem4Id()).orElse(null));
		build.setItem5(itemsRepository.findById(build.getItem5Id()).orElse(null));
		build.setItem6(itemsRepository.findById(build.getItem6Id()).orElse(null));
		build.setSummonerSpell1(summonerSpellsRepository.findById(build.getSummonerSpell1Id()).orElse(null));
		build.setSummonerSpell2(summonerSpellsRepository.findById(build.getSummonerSpell2Id()).orElse(null));
		build.setTrinket(itemsRepository.findById(build.getTrinketId()).orElse(null));
		build.setMap(mapsRepository.findById(build.getMapId()).orElse(null));

		BindingResult result = new BeanPropertyBindingResult(build, "build");
		build.validate(build, result);
		if (result.hasErrors()) {
			throw new BadRequestException(result.getFieldErrors());
		}
		return build;
	}

	/**
	 * Saves a {@link Build}.
	 *
	 * @param build the {@link Build} to save, if valid
	 * @return the {@link Build}
	 */
	@JsonView({ ApiViews.LtbApi.class })
	@PostMapping
	@ResponseStatus(HttpStatus.CREATED)
	@ResponseBody
	public ResponseEntity<Build> saveBuild(@RequestBody @Valid Build build, BindingResult bindingResult) {
		if (bindingResult.hasErrors()) {
			throw new BadRequestException(bindingResult.getFieldErrors());
		}
		Build savedBuild = buildsRepository.save(build);
		return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest()
				.path("/{id}")
				.buildAndExpand(savedBuild.getId())
				.toUri())
				.body(savedBuild);
	}

	/**
	 * Gets the number of saved {@link Build}s.
	 *
	 * @return the count of saved {@link Build}s
	 */
	@GetMapping(path = "/count")
	public long countBuilds() {
		return buildsRepository.count();
	}

}

@@ -441,71 +441,8 @@
 ed;%0A
-import org.springframework.beans.factory.annotation.Qualifier;%0A
 impo
@@ -481,24 +481,24 @@
 in.Example;%0A
+
 import org.s
@@ -956,108 +956,8 @@
 lt;%0A
-import org.springframework.validation.Validator;%0Aimport org.springframework.web.bind.WebDataBinder;%0A
 impo
@@ -1579,32 +1579,32 @@
 y;%0A%0A%09@Autowired%0A
+
 %09private MapsRep
@@ -1632,178 +1632,8 @@
 y;%0A%0A
-%09@Autowired%0A%09@Qualifier(%22mvcValidator%22)%0A%09private Validator validator;%0A%0A%09@InitBinder%0A%09public void initBinder(WebDataBinder binder) %7B%0A%09%09binder.setValidator(validator);%0A%09%7D%0A%0A
 %09/**

Remove binder.setValidator