package vn.azteam.tpf.web.rest;

import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.Lists;
import io.github.jhipster.service.filter.LongFilter;
import org.springframework.data.domain.PageImpl;
import vn.azteam.tpf.Constants.Constants;
import vn.azteam.tpf.service.TBActivityExtendTypeService;
import vn.azteam.tpf.service.TBObjectParameterService;
import vn.azteam.tpf.service.dto.*;
import vn.azteam.tpf.service.util.PageableUtil;
import vn.azteam.tpf.web.rest.errors.BadRequestAlertException;
import vn.azteam.tpf.web.rest.util.HeaderUtil;
import vn.azteam.tpf.web.rest.util.PaginationUtil;
import vn.azteam.tpf.service.TBObjectParameterQueryService;
import vn.azteam.tpf.service.UserService;
import io.github.jhipster.web.util.ResponseUtil;
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.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.net.URISyntaxException;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

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

    private final Logger log = LoggerFactory.getLogger(TBObjectParameterResource.class);

    private static final String ENTITY_NAME = "tBObjectParameter";

    private final TBObjectParameterService tBObjectParameterService;

    private final UserService userService;

    private final TBObjectParameterQueryService tBObjectParameterQueryService;

    private final TBActivityExtendTypeService tbActivityExtendTypeService;

    private final PageableUtil pageableUtil;

    public TBObjectParameterResource(TBObjectParameterService tBObjectParameterService,
                                     UserService userService,
                                     TBObjectParameterQueryService tBObjectParameterQueryService,
                                     TBActivityExtendTypeService tbActivityExtendTypeService, PageableUtil pageableUtil) {
        this.tBObjectParameterService = tBObjectParameterService;
        this.userService = userService;
        this.tBObjectParameterQueryService = tBObjectParameterQueryService;
        this.tbActivityExtendTypeService = tbActivityExtendTypeService;
        this.pageableUtil = pageableUtil;
    }

    /**
     * POST  /tb-object-parameters : Create a new tBObjectParameter.
     *
     * @param tBObjectParameterDTO the tBObjectParameterDTO to create
     * @return the ResponseEntity with status 201 (Created) and with body the new tBObjectParameterDTO, or with status 400 (Bad Request) if the tBObjectParameter has already an ID
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/tb-object-parameters")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> createTBObjectParameter(@RequestBody TBObjectParameterDTO tBObjectParameterDTO) throws URISyntaxException {
        log.debug("REST request to save TBObjectParameter : {}", tBObjectParameterDTO);
        if (tBObjectParameterDTO.getId() != null) {
            throw new BadRequestAlertException("A new tBObjectParameter cannot already have an ID", ENTITY_NAME, "idexists");
        }
        TBObjectParameterDTO result = tBObjectParameterService.save(tBObjectParameterDTO);
        return ResponseEntity.created(new URI("/api/tb-object-parameters/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
            .body(result);
    }

    /**
     * PUT  /tb-object-parameters : Updates an existing tBObjectParameter.
     *
     * @param tBObjectParameterDTO the tBObjectParameterDTO to update
     * @return the ResponseEntity with status 200 (OK) and with body the updated tBObjectParameterDTO,
     * or with status 400 (Bad Request) if the tBObjectParameterDTO is not valid,
     * or with status 500 (Internal Server Error) if the tBObjectParameterDTO couldn't be updated
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PutMapping("/tb-object-parameters")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> updateTBObjectParameter(@RequestBody TBObjectParameterDTO tBObjectParameterDTO) throws URISyntaxException {
        log.debug("REST request to update TBObjectParameter : {}", tBObjectParameterDTO);
        if (tBObjectParameterDTO.getId() == null) {
            throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
        }
        TBObjectParameterDTO result = tBObjectParameterService.save(tBObjectParameterDTO);
        return ResponseEntity.ok()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, tBObjectParameterDTO.getId().toString()))
            .body(result);
    }

    /**
     * GET  /tb-object-parameters : get all the tBObjectParameters.
     *
     * @param pageable the pagination information
     * @param criteria the criterias which the requested entities should match
     * @return the ResponseEntity with status 200 (OK) and the list of tBObjectParameters in body
     */
    @GetMapping("/tb-object-parameters")
    @Timed
    public ResponseEntity<List<TBObjectParameterDTO>> getAllTBObjectParameters(TBObjectParameterCriteria criteria, Pageable pageable) {
        log.debug("REST request to get TBObjectParameters by criteria: {}", criteria);
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Page<TBObjectParameterDTO> page = tBObjectParameterQueryService.findByCriteria(criteria, pageable);
        if (currentUser.getCustomerId() != null) {
            List<TBObjectParameterDTO> tbObjectParameterDTOList = page.getContent().stream()
                .filter(item -> item.getTbCustomerId() == currentUser.getCustomerId() || item.getTbCustomerId() == null)
                .collect(Collectors.toList());
            page = pageableUtil.changeTBObjectParameterDTOToPageFromList(tbObjectParameterDTOList, pageable);
        }
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tb-object-parameters");
        return ResponseEntity.ok().headers(headers).body(page.getContent());
    }

    /**
     * GET  /tb-object-parameters/count : count all the tBObjectParameters.
     *
     * @param criteria the criterias which the requested entities should match
     * @return the ResponseEntity with status 200 (OK) and the count in body
     */
    @GetMapping("/tb-object-parameters/count")
    @Timed
    public ResponseEntity<Long> countTBObjectParameters(TBObjectParameterCriteria criteria) {
        log.debug("REST request to count TBObjectParameters by criteria: {}", criteria);
        return ResponseEntity.ok().body(tBObjectParameterQueryService.countByCriteria(criteria));
    }

    /**
     * GET  /tb-object-parameters/:id : get the "id" tBObjectParameter.
     *
     * @param id the id of the tBObjectParameterDTO to retrieve
     * @return the ResponseEntity with status 200 (OK) and with body the tBObjectParameterDTO, or with status 404 (Not Found)
     */
    @GetMapping("/tb-object-parameters/{id}")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> getTBObjectParameter(@PathVariable Long id) {
        log.debug("REST request to get TBObjectParameter : {}", id);
        Optional<TBObjectParameterDTO> tBObjectParameterDTO = tBObjectParameterService.findOne(id);
        return ResponseUtil.wrapOrNotFound(tBObjectParameterDTO);
    }

    /**
     * DELETE  /tb-object-parameters/:id : delete the "id" tBObjectParameter.
     *
     * @param id the id of the tBObjectParameterDTO to delete
     * @return the ResponseEntity with status 200 (OK)
     */
    @DeleteMapping("/tb-object-parameters/{id}")
    @Timed
    public ResponseEntity<Void> deleteTBObjectParameter(@PathVariable Long id) {
        log.debug("REST request to delete TBObjectParameter : {}", id);
        tBObjectParameterService.delete(id);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }

    /**
     * SEARCH  /_search/tb-object-parameters?query=:query : search for the tBObjectParameter corresponding
     * to the query.
     *
     * @param query    the query of the tBObjectParameter search
     * @param pageable the pagination information
     * @return the result of the search
     */
    @GetMapping("/_search/tb-object-parameters")
    @Timed
    public ResponseEntity<List<TBObjectParameterDTO>> searchTBObjectParameters(@RequestParam String query, Pageable pageable) {
        log.debug("REST request to search for a page of TBObjectParameters for query {}", query);
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Page<TBObjectParameterDTO> page = tBObjectParameterService.search(query, pageable);
        if (currentUser.getCustomerId() != null) {
            List<TBObjectParameterDTO> tbObjectParameterDTOList = page.getContent().stream()
                .filter(item -> item.getTbCustomerId() == currentUser.getCustomerId() || item.getTbCustomerId() == null)
                .collect(Collectors.toList());
            page = pageableUtil.changeTBObjectParameterDTOToPageFromList(tbObjectParameterDTOList, pageable);
        }
        HttpHeaders headers = PaginationUtil.generateSearchPaginationHttpHeaders(query, page, "/api/_search/tb-object-parameters");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    @GetMapping("/tb-object-parameters-param-list/{activityTypeId}")
    @Timed
    public ResponseEntity<List<TBObjectParameterDTO>> getAllTBObjectParametersForParamList(@PathVariable Long activityTypeId,
                                                                                           Pageable pageable) {
        TBObjectParameterCriteria criteria = new TBObjectParameterCriteria();
        log.debug("REST request to get TBObjectParameters by criteria: {}", criteria);
        UserDTO currentUser = userService.getCurrentUserDTO().get();

        //Filter by activity type id
        LongFilter activityTypeFilter = new LongFilter();
        activityTypeFilter.setEquals(activityTypeId);
        criteria.setActivityTypeId(activityTypeFilter);

        List<TBObjectParameterDTO> tbObjectParameterDTOs = tBObjectParameterQueryService.findByCriteria(criteria);

        //Filter tbActivityExtendTypeId is null
        List<TBObjectParameterDTO> tbObjectParameterDTOTempList = tbObjectParameterDTOs.stream()
            .filter(item -> item.getTbActivityExtendTypeId() == null)
            .collect(Collectors.toList());

        if (currentUser.getCustomerId() != null) {
            tbObjectParameterDTOTempList = tbObjectParameterDTOTempList.stream()
                .filter(item -> item.getTbCustomerId() == currentUser.getCustomerId() || item.getTbCustomerId() == null)
                .collect(Collectors.toList());

        }
        Page<TBObjectParameterDTO> page = pageableUtil.changeTBObjectParameterDTOToPageFromList(tbObjectParameterDTOTempList, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tb-object-parameters-param-list");
        return ResponseEntity.ok().headers(headers).body(page.getContent());
    }

    @GetMapping("/tb-object-param-has-extend-type-list/{activityTypeId}")
    @Timed
    public ResponseEntity<List<TBObjectParameterDTO>> getAllTBObjectParamHasExtendTypeList(@PathVariable Long activityTypeId,
                                                                                           Pageable pageable) {
        TBObjectParameterCriteria criteria = new TBObjectParameterCriteria();
        log.debug("REST request to get TBObjectParameters by criteria: {}", criteria);
        UserDTO currentUser = userService.getCurrentUserDTO().get();

        //Filter by activity type id
        LongFilter activityTypeFilter = new LongFilter();
        activityTypeFilter.setEquals(activityTypeId);
        criteria.setActivityTypeId(activityTypeFilter);

        List<TBObjectParameterDTO> tbObjectParameterDTOs = tBObjectParameterQueryService.findByCriteria(criteria);

        //Filter tbActivityExtendTypeId is null
        List<TBObjectParameterDTO> tbObjectParameterDTOTempList = tbObjectParameterDTOs.stream()
            .filter(item -> item.getTbActivityExtendTypeId() != null)
            .collect(Collectors.toList());

        if (currentUser.getCustomerId() != null) {
            tbObjectParameterDTOTempList = tbObjectParameterDTOTempList.stream()
                .filter(item -> item.getTbCustomerId() == currentUser.getCustomerId() || item.getTbCustomerId() == null)
                .collect(Collectors.toList());
        }
        Page<TBObjectParameterDTO> page = pageableUtil.changeTBObjectParameterDTOToPageFromList(tbObjectParameterDTOTempList, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tb-object-param-has-extend-type-list");
        return ResponseEntity.ok().headers(headers).body(page.getContent());
    }

    @GetMapping("/tb-object-param-has-extend-type/{id}")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> getTBObjectParameterHasExtendType(@PathVariable Long id) {
        log.debug("REST request to get TBObjectParameter has extend type : {}", id);
        Optional<TBObjectParameterDTO> tBObjectParameterDTO = tBObjectParameterService.findOne(id);
        return ResponseUtil.wrapOrNotFound(tBObjectParameterDTO);
    }

    @PostMapping("/tb-object-param-has-extend-type")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> createTBObjectParameterHasExtendType(@RequestBody TBObjectParamHasExtendTypeDTO tbObjectParamHasExtendTypeDTO) throws URISyntaxException {
        log.debug("REST request to save TBObjectParameter has extend type : {}", tbObjectParamHasExtendTypeDTO);
        if (tbObjectParamHasExtendTypeDTO.getTbObjectParameterDTO().getId() != null) {
            throw new BadRequestAlertException("A new tBObjectParameter has extend type cannot already have an ID", ENTITY_NAME, "idexists");
        }
        TBObjectParameterDTO paramTBObjectParameterDTO = tbObjectParamHasExtendTypeDTO.getTbObjectParameterDTO();
        TBActivityExtendTypeDTO paramTBActivityExtendTypeDTO = tbObjectParamHasExtendTypeDTO.getTbActivityExtendTypeDTO();
        paramTBActivityExtendTypeDTO.setActivityTypeId(paramTBObjectParameterDTO.getActivityTypeId());
        paramTBActivityExtendTypeDTO.setIsGuidelineUsing(paramTBObjectParameterDTO.getIsGuidelineUsing());
        paramTBActivityExtendTypeDTO.setObjectType(Constants.OBJECT_TYPE);

        TBActivityExtendTypeDTO tbActivityExtendTypeDTO = tbActivityExtendTypeService.save(paramTBActivityExtendTypeDTO);
        paramTBObjectParameterDTO.setTbActivityExtendTypeId(tbActivityExtendTypeDTO.getId());
        TBObjectParameterDTO result = tBObjectParameterService.save(paramTBObjectParameterDTO);
        return ResponseEntity.created(new URI("/api/tb-object-parameters-has-extend-type/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
            .body(result);
    }

    @PutMapping("/tb-object-param-has-extend-type")
    @Timed
    public ResponseEntity<TBObjectParameterDTO> updateTBObjectParameterHasExtendType(@RequestBody TBObjectParamHasExtendTypeDTO tbObjectParamHasExtendTypeDTO) throws URISyntaxException {
        log.debug("REST request to update TBObjectParameter has extend type : {}", tbObjectParamHasExtendTypeDTO);
        if (tbObjectParamHasExtendTypeDTO.getTbObjectParameterDTO().getId() == null) {
            throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
        }
        TBObjectParameterDTO paramTBObjectParameterDTO = tbObjectParamHasExtendTypeDTO.getTbObjectParameterDTO();
        TBActivityExtendTypeDTO paramTBActivityExtendTypeDTO = tbObjectParamHasExtendTypeDTO.getTbActivityExtendTypeDTO();
        paramTBActivityExtendTypeDTO.setActivityTypeId(paramTBObjectParameterDTO.getActivityTypeId());
        paramTBActivityExtendTypeDTO.setIsGuidelineUsing(paramTBObjectParameterDTO.getIsGuidelineUsing());
        paramTBActivityExtendTypeDTO.setObjectType(Constants.OBJECT_TYPE);

        TBActivityExtendTypeDTO tbActivityExtendTypeDTO = tbActivityExtendTypeService.save(paramTBActivityExtendTypeDTO);
        paramTBObjectParameterDTO.setTbActivityExtendTypeId(tbActivityExtendTypeDTO.getId());
        TBObjectParameterDTO result = tBObjectParameterService.save(paramTBObjectParameterDTO);
        return ResponseEntity.ok()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, result.getId().toString()))
            .body(result);
    }

    @DeleteMapping("/tb-object-param-has-extend-type/{id}")
    @Timed
    public ResponseEntity<Void> deleteTBObjectParameterHasExtendType(@PathVariable Long id) {
        log.debug("REST request to delete TBObjectParameter has extend type: {}", id);
        TBObjectParameterDTO tbObjectParameterDTO= tBObjectParameterService.findOne(id).get();
        tBObjectParameterService.delete(id);
        tbActivityExtendTypeService.delete(tbObjectParameterDTO.getTbActivityExtendTypeId());
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }
}
