package org.skilltracker.app.web.rest;

import com.codahale.metrics.annotation.Timed;
import org.skilltracker.app.domain.Enrolment;
import org.skilltracker.app.repository.EnrolmentRepository;
import org.skilltracker.app.repository.search.EnrolmentSearchRepository;
import org.skilltracker.app.web.rest.util.HeaderUtil;
import org.skilltracker.app.web.rest.util.PaginationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.inject.Inject;
import javax.validation.Valid;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static org.elasticsearch.index.query.QueryBuilders.*;

/**
 * REST controller for managing Enrolment.
 */
@RestController
@RequestMapping("/api")
public class EnrolmentResource {

    private final Logger log = LoggerFactory.getLogger(EnrolmentResource.class);
        
    @Inject
    private EnrolmentRepository enrolmentRepository;
    
    @Inject
    private EnrolmentSearchRepository enrolmentSearchRepository;
    
    /**
     * POST  /enrolments -> Create a new enrolment.
     */
    @RequestMapping(value = "/enrolments",
        method = RequestMethod.POST,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public ResponseEntity<Enrolment> createEnrolment(@Valid @RequestBody Enrolment enrolment) throws URISyntaxException {
        log.debug("REST request to save Enrolment : {}", enrolment);
        if (enrolment.getId() != null) {
            return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("enrolment", "idexists", "A new enrolment cannot already have an ID")).body(null);
        }
        Enrolment result = enrolmentRepository.save(enrolment);
        enrolmentSearchRepository.save(result);
        return ResponseEntity.created(new URI("/api/enrolments/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert("enrolment", result.getId().toString()))
            .body(result);
    }

    /**
     * PUT  /enrolments -> Updates an existing enrolment.
     */
    @RequestMapping(value = "/enrolments",
        method = RequestMethod.PUT,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public ResponseEntity<Enrolment> updateEnrolment(@Valid @RequestBody Enrolment enrolment) throws URISyntaxException {
        log.debug("REST request to update Enrolment : {}", enrolment);
        if (enrolment.getId() == null) {
            return createEnrolment(enrolment);
        }
        Enrolment result = enrolmentRepository.save(enrolment);
        enrolmentSearchRepository.save(result);
        return ResponseEntity.ok()
            .headers(HeaderUtil.createEntityUpdateAlert("enrolment", enrolment.getId().toString()))
            .body(result);
    }

    /**
     * GET  /enrolments -> get all the enrolments.
     */
    @RequestMapping(value = "/enrolments",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public ResponseEntity<List<Enrolment>> getAllEnrolments(Pageable pageable)
        throws URISyntaxException {
        log.debug("REST request to get a page of Enrolments");
        Page<Enrolment> page = enrolmentRepository.findAll(pageable); 
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/enrolments");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    /**
     * GET  /enrolments/:id -> get the "id" enrolment.
     */
    @RequestMapping(value = "/enrolments/{id}",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public ResponseEntity<Enrolment> getEnrolment(@PathVariable Long id) {
        log.debug("REST request to get Enrolment : {}", id);
        Enrolment enrolment = enrolmentRepository.findOne(id);
        return Optional.ofNullable(enrolment)
            .map(result -> new ResponseEntity<>(
                result,
                HttpStatus.OK))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * DELETE  /enrolments/:id -> delete the "id" enrolment.
     */
    @RequestMapping(value = "/enrolments/{id}",
        method = RequestMethod.DELETE,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public ResponseEntity<Void> deleteEnrolment(@PathVariable Long id) {
        log.debug("REST request to delete Enrolment : {}", id);
        enrolmentRepository.delete(id);
        enrolmentSearchRepository.delete(id);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("enrolment", id.toString())).build();
    }

    /**
     * SEARCH  /_search/enrolments/:query -> search for the enrolment corresponding
     * to the query.
     */
    @RequestMapping(value = "/_search/enrolments/{query}",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public List<Enrolment> searchEnrolments(@PathVariable String query) {
        log.debug("REST request to search Enrolments for query {}", query);
        return StreamSupport
            .stream(enrolmentSearchRepository.search(queryStringQuery(query)).spliterator(), false)
            .collect(Collectors.toList());
    }
}
