package vn.azteam.tpf.web.rest;

import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import io.github.jhipster.service.filter.BooleanFilter;
import io.github.jhipster.service.filter.IntegerFilter;
import io.github.jhipster.service.filter.LongFilter;
import org.casbin.jcasbin.main.Enforcer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import vn.azteam.tpf.Constants.Constants;
import vn.azteam.tpf.repository.CasbinRepository;
import vn.azteam.tpf.service.*;
import vn.azteam.tpf.service.dto.*;
import vn.azteam.tpf.service.mapper.CasbinMapper;
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 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 javax.transaction.Transactional;
import java.net.URI;
import java.net.URISyntaxException;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import static vn.azteam.tpf.Constants.Constants.OBJECT_EXTEND_TYPE.*;

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

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

    private static final String ENTITY_NAME = "tBActivityType";

    private final TBActivityTypeService tBActivityTypeService;

    private final TBCropService tbCropService;

    private final TBCropTypeService tbCropTypeService;

    private final UserService userService;

    private final TBActivityTypeQueryService tBActivityTypeQueryService;

    private final ObjectMapper objectMapper;

    private final TBObjectParameterQueryService tbObjectParameterQueryService;

    private final TBActivityExtendTypeQueryService tbActivityExtendTypeQueryService;

    private final TBFunctionService tbFunctionService;

    private final TBRoleService tbRoleService;

    private final CasbinRepository casbinRepository;

    private final CasbinMapper casbinMapper;

    private final PageableUtil pageableUtil;
    @Autowired
    private final ApplicationContext context;

    public TBActivityTypeResource(TBActivityTypeService tBActivityTypeService,
                                  TBCropService tbCropService, TBCropTypeService tbCropTypeService,
                                  UserService userService,
                                  TBActivityTypeQueryService tBActivityTypeQueryService,
                                  ObjectMapper objectMapper,
                                  TBObjectParameterQueryService tbObjectParameterQueryService,
                                  TBActivityExtendTypeQueryService tbActivityExtendTypeQueryService,
                                  TBFunctionService tbFunctionService,
                                  TBRoleService tbRoleService,
                                  CasbinRepository casbinRepository,
                                  CasbinMapper casbinMapper,
                                  PageableUtil pageableUtil,
                                  ApplicationContext context) {
        this.tBActivityTypeService = tBActivityTypeService;
        this.tbCropService = tbCropService;
        this.tbCropTypeService = tbCropTypeService;
        this.userService = userService;
        this.tBActivityTypeQueryService = tBActivityTypeQueryService;
        this.objectMapper = objectMapper;
        this.tbObjectParameterQueryService = tbObjectParameterQueryService;
        this.tbActivityExtendTypeQueryService = tbActivityExtendTypeQueryService;
        this.tbFunctionService = tbFunctionService;
        this.tbRoleService = tbRoleService;
        this.casbinRepository = casbinRepository;
        this.casbinMapper = casbinMapper;
        this.pageableUtil = pageableUtil;
        this.context = context;
    }

    /**
     * POST  /tb-activity-types : Create a new tBActivityType.
     *
     * @param strTBActivityTypeDTO the tBActivityTypeDTO to create
     * @return the ResponseEntity with status 201 (Created) and with body the new tBActivityTypeDTO, or with status 400 (Bad Request) if the tBActivityType has already an ID
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/tb-activity-types")
    @Transactional
    @Timed
    public ResponseEntity<TBActivityTypeDTO> createTBActivityType(@RequestParam("strTBActivityTypeDTO") String strTBActivityTypeDTO,
                                                                  @RequestParam(value = "images") MultipartFile[] images) throws URISyntaxException {
        log.debug("REST request to save TBActivityType : {}", strTBActivityTypeDTO);
        TBActivityTypeDTO tbActivityTypeDTO = parseActivityTypeDTOFromJsonString(strTBActivityTypeDTO);
        if (tbActivityTypeDTO.getId() != null) {
            throw new BadRequestAlertException("A new tBActivityType cannot already have an ID", ENTITY_NAME, "idexists");
        }
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        // Set created by and created date
        tbActivityTypeDTO.setCreatedById(currentUser.getId());
        tbActivityTypeDTO.setCreatedDate(Instant.now());
        // Set is can delete
        tbActivityTypeDTO.setIsCanDelete(Boolean.TRUE);

        tbActivityTypeDTO = tBActivityTypeQueryService.saveUploadedFiles(tbActivityTypeDTO, images);
        TBActivityTypeDTO result = tBActivityTypeService.save(tbActivityTypeDTO);

        if(result.getId() != null){
            //Create list CRUD by new dynamic activityTypes
            List<TBFunctionDTO> tbFunctionDTODynamicList = new ArrayList<>();
            for (Constants.METHODS_DYNAMIC method: Constants.METHODS_DYNAMIC.values()) {
                TBFunctionDTO tbFunctionDTO = new TBFunctionDTO();
                tbFunctionDTO.setName(method.getValue() + result.getDescription().toLowerCase());
                tbFunctionDTO.setTypeRequest("*");
                String path_str = Constants.METHODS_PATH_ACTIVITY_TYPE.valueOf(method.name()).getValue() + result.getName() + "*";
                tbFunctionDTO.setPath(path_str);
                tbFunctionDTO.setMethod(Constants.METHODS_PATH_ACTIVITY_TYPE.valueOf(method.name()).getName());
                tbFunctionDTO.setTbFunctionGroupId(3L);
                tbFunctionDTO = tbFunctionService.save(tbFunctionDTO);
                tbFunctionDTODynamicList.add(tbFunctionDTO);
            }
            //Create casbin for all role
            if(tbFunctionDTODynamicList.size() > 0) {
                //Get list roles
                List<TBRoleDTO> tbRoleDTOSAll = tbRoleService.findAll(Pageable.unpaged()).getContent();
                tbRoleDTOSAll.forEach(role -> {
                    tbFunctionDTODynamicList.forEach(func -> {
                        CasbinDTO casbinDTO = new CasbinDTO();
                        casbinDTO.setpType("p");
                        casbinDTO.setV0(role.getId().toString());
                        casbinDTO.setV1(func.getPath());
                        casbinDTO.setV2(func.getMethod());
                        casbinDTO.setV3("*");
                        casbinDTO.setV4("true");
                        String v5 = func.getMethod().toLowerCase() + func.getPath().replaceAll("[^a-zA-Z0-9]","").toLowerCase();
                        casbinDTO.setV5(v5);
                        casbinDTO.setTbRoleId(role.getId());
                        casbinDTO.setTbFunctionId(func.getId());
                        casbinDTO.setCreatedDate(Instant.now().getEpochSecond());
                        casbinDTO.setCreatedById(currentUser.getId());
                        casbinRepository.saveAndFlush(casbinMapper.toEntity(casbinDTO));
                        Enforcer enforcer = context.getBean(Enforcer.class);
                        enforcer.loadPolicy();
                    });
                });
            }
        }

        return ResponseEntity.created(new URI("/api/tb-activity-types/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
            .body(result);
    }



    /**
     * PUT  /tb-activity-types : Updates an existing tBActivityType.
     *
     * @param strTBActivityTypeDTO the tBActivityTypeDTO to update
     * @return the ResponseEntity with status 200 (OK) and with body the updated tBActivityTypeDTO,
     * or with status 400 (Bad Request) if the tBActivityTypeDTO is not valid,
     * or with status 500 (Internal Server Error) if the tBActivityTypeDTO couldn't be updated
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/update-tb-activity-types")
    @Transactional
    @Timed
    public ResponseEntity<TBActivityTypeDTO> updateTBActivityType(@RequestParam("strTBActivityTypeDTO") String strTBActivityTypeDTO,
                                                                  @RequestParam(value = "images") MultipartFile[] images) throws URISyntaxException {
        TBActivityTypeDTO tbActivityTypeDTO = parseActivityTypeDTOFromJsonString(strTBActivityTypeDTO);
        log.debug("REST request to update TBActivityType : {}", strTBActivityTypeDTO);
        if (tbActivityTypeDTO.getId() == null) {
            throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
        }
        TBActivityTypeDTO tbActivityTypeDTOPrevious = tBActivityTypeService.findOne(tbActivityTypeDTO.getId()).get();
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        // Set created by and created date
        tbActivityTypeDTO.setModifiedById(currentUser.getId());
        tbActivityTypeDTO.setModifiedDate(Instant.now());
        tbActivityTypeDTO.setIsCanDelete(tbActivityTypeDTOPrevious.getIsCanDelete());

        // Override upload icon activity type when change image
        if(images != null) {
            String deletedImage = null;
            String urlLogo = tbActivityTypeDTO.getUrlLogo();
            if(urlLogo != null && urlLogo != Constants.EMPTY) {
                String[] arrDeletedImage = urlLogo.split(Constants.SLASH);
                deletedImage = arrDeletedImage[arrDeletedImage.length-1];
            }
            tbActivityTypeDTO = tBActivityTypeQueryService.updateUploadedFiles(tbActivityTypeDTO, images, deletedImage);
        }

        TBActivityTypeDTO result = tBActivityTypeService.save(tbActivityTypeDTO);
        //get list path api map with previous activity type
        List<String> listPathFull = genListPathByNameAndArrayMethods(tbActivityTypeDTOPrevious.getName());
        //Filter function on listPathFull
        List<TBFunctionDTO> tbFunctionDTOOld = tbFunctionService.findAll(Pageable.unpaged()).getContent()
            .stream()
            .filter(func -> listPathFull.contains(func.getPath()))
            .collect(Collectors.toList());
        if(tbFunctionDTOOld.size() > 0) {
            //Get list id function be updated
            List<Long> listFuncIds = tbFunctionDTOOld.stream().map(TBFunctionDTO::getId).collect(Collectors.toList());
            List<CasbinDTO> casbinDTOS = casbinMapper.toDto(casbinRepository.findAll())
                .stream()
                .filter(casbin -> listFuncIds.contains(casbin.getTbFunctionId()))
                .collect(Collectors.toList());
            tbFunctionDTOOld.forEach(func -> {
                //gen path api full for activity type
                String path_str = "";
                String name_str = "";

                //update function activity
                List<Constants.METHODS_PATH_ACTIVITY_TYPE> somethingList =
                    new ArrayList<>(EnumSet.allOf(Constants.METHODS_PATH_ACTIVITY_TYPE.class));

                Constants.METHODS_PATH_ACTIVITY_TYPE selectedItem = null;
                for (Constants.METHODS_PATH_ACTIVITY_TYPE item : somethingList) {
                    if(func.getPath().contains(item.getValue())) {
                        selectedItem = item;
                        break;
                    }
                }
                if(selectedItem != null) {
                    path_str = selectedItem.getValue() + result.getName() + "*";
                    name_str = Constants.METHODS_DYNAMIC.valueOf(selectedItem.toString()).getValue() + result.getDescription().toLowerCase();
                }

                func.setName(name_str);
                func.setPath(path_str);
                //Update function table
                tbFunctionService.save(func);
                //Update casbin table
                casbinDTOS.stream()
                    .filter(casbin -> casbin.getTbFunctionId().equals(func.getId()))
                    .forEach(casbin -> {
                        casbin.setV1(func.getPath());
                        String v5 = func.getMethod().toLowerCase() + func.getPath().replaceAll("[^a-zA-Z0-9]","").toLowerCase();
                        casbin.setV5(v5);
                        casbin.setModifiedDate(Instant.now().getEpochSecond());
                        casbin.setModifiedById(currentUser.getId());
                        casbinRepository.saveAndFlush(casbinMapper.toEntity(casbin));
                        Enforcer enforcer = context.getBean(Enforcer.class);
                        enforcer.loadPolicy();
                    });
            });
        }
        return ResponseEntity.ok()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, tbActivityTypeDTO.getId().toString()))
            .body(result);
    }

    private List<String> genListPathByNameAndArrayMethods(String name){
        List<String> result = new ArrayList<>();
        if(name == null || name.isEmpty()){
            return Lists.newArrayList();
        }
        //for activity
        for (Constants.METHODS_PATH_ACTIVITY_TYPE method: Constants.METHODS_PATH_ACTIVITY_TYPE.values()) {
            String path_full = method.getValue() + name + "*";
            result.add(path_full);
        }
        return result;
    }


    private TBActivityTypeDTO parseActivityTypeDTOFromJsonString(String data_request) {
        TBActivityTypeDTO data;
        try {
            data = this.objectMapper.readValue(data_request, TBActivityTypeDTO.class);
        } catch (Exception e) {
            throw new BadRequestAlertException(e.getMessage(), ENTITY_NAME, "parseError");
        }
        return data;
    }

    /**
     * GET  /tb-activity-types : get all the tBActivityTypes.
     *
     * @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 tBActivityTypes in body
     */
    @GetMapping("/tb-activity-types")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> getAllTBActivityTypes(TBActivityTypeCriteria criteria, Pageable pageable) {
        log.debug("REST request to get TBActivityTypes by criteria: {}", criteria);
        Page<TBActivityTypeDTO> page = tBActivityTypeQueryService.findByCriteria(criteria, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tb-activity-types");
        return ResponseEntity.ok().headers(headers).body(page.getContent());
    }

    @GetMapping("/tb-activity-types-dropdown-list")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> getAllTBActivityTypesDropdown(TBActivityTypeCriteria criteria) {
        log.debug("REST request to get TBActivityTypes by criteria: {}", criteria);
        BooleanFilter isUsingGuidelineFilter = new BooleanFilter();
        isUsingGuidelineFilter.setEquals(true);
        criteria.setIsGuidelineUsing(isUsingGuidelineFilter);
        List<TBActivityTypeDTO> tbActivityTypeDTOs = tBActivityTypeQueryService.findByCriteria(criteria);
        return ResponseEntity.ok().headers(null).body(tbActivityTypeDTOs);
    }

    /**
    * GET  /tb-activity-types/count : count all the tBActivityTypes.
    *
    * @param criteria the criterias which the requested entities should match
    * @return the ResponseEntity with status 200 (OK) and the count in body
    */
    @GetMapping("/tb-activity-types/count")
    @Timed
    public ResponseEntity<Long> countTBActivityTypes(TBActivityTypeCriteria criteria) {
        log.debug("REST request to count TBActivityTypes by criteria: {}", criteria);
        return ResponseEntity.ok().body(tBActivityTypeQueryService.countByCriteria(criteria));
    }

    /**
     * GET  /tb-activity-types/:id : get the "id" tBActivityType.
     *
     * @param id the id of the tBActivityTypeDTO to retrieve
     * @return the ResponseEntity with status 200 (OK) and with body the tBActivityTypeDTO, or with status 404 (Not Found)
     */
    @GetMapping("/tb-activity-types/{id}")
    @Timed
    public ResponseEntity<TBActivityTypeDTO> getTBActivityType(@PathVariable Long id) {
        log.debug("REST request to get TBActivityType : {}", id);
        Optional<TBActivityTypeDTO> tBActivityTypeDTO = tBActivityTypeService.findOne(id);
        return ResponseUtil.wrapOrNotFound(tBActivityTypeDTO);
    }

    /**
     * GET  /tb-activity-types/:id : get the "id" tBActivityType.
     *
     * @param id the id of the tBActivityTypeDTO to retrieve
     * @return the ResponseEntity with status 200 (OK) and with body the tBActivityTypeDTO, or with status 404 (Not Found)
     */
    @GetMapping("/tb-activity-types-name/{id}")
    @Timed
    public ResponseEntity<?> getTBActivityTypeNameById(@PathVariable Long id) {
        log.debug("REST request to get TBActivityType : {}", id);
        HashMap<String,String> result = new HashMap<String,String>();
        Optional<TBActivityTypeDTO> tBActivityTypeDTO = tBActivityTypeService.findOne(id);
        if(tBActivityTypeDTO.isPresent() && !tBActivityTypeDTO.get().getName().isEmpty()) {
            result.put("name", tBActivityTypeDTO.get().getName());
            result.put("id", tBActivityTypeDTO.get().getId().toString());
            result.put("description", tBActivityTypeDTO.get().getDescription());

        }
        return new ResponseEntity(result, result.size() > 0 ? HttpStatus.OK : HttpStatus.NOT_FOUND);
    }

    /**
     * DELETE  /tb-activity-types/:id : delete the "id" tBActivityType.
     *
     * @param id the id of the tBActivityTypeDTO to delete
     * @return the ResponseEntity with status 200 (OK)
     */
    @DeleteMapping("/tb-activity-types/{id}")
    @Transactional
    @Timed
    public ResponseEntity<Void> deleteTBActivityType(@PathVariable Long id) {
        log.debug("REST request to delete TBActivityType : {}", id);
        TBActivityTypeDTO tbActivityTypeDTO = tBActivityTypeService.findOne(id).get();
        if(!tbActivityTypeDTO.getIsCanDelete()) {
            throw new BadRequestAlertException("1052", ENTITY_NAME, "1052");
        }
        tBActivityTypeService.delete(id);
        List<String> listPathFull = genListPathByNameAndArrayMethods(tbActivityTypeDTO.getName());
        //Update function table
        List<Long> tbFunctionDTOIds = tbFunctionService.findAll(Pageable.unpaged()).getContent()
            .stream()
            .filter(func -> listPathFull.contains(func.getPath()))
            .map(TBFunctionDTO::getId)
            .collect(Collectors.toList());
        //Delete list casbin_rule
        casbinRepository.findAll(Pageable.unpaged()).forEach(casbin -> {
            if (tbFunctionDTOIds.contains(casbin.getTbFunction().getId())){
                casbinRepository.delete(casbin);
            }
        });
        //Delete list functions
        tbFunctionService.findAll(Pageable.unpaged()).forEach(func -> {
            if (tbFunctionDTOIds.contains(func.getId())){
                tbFunctionService.delete(func.getId());
            }
        });
        Enforcer enforcer = context.getBean(Enforcer.class);
        enforcer.loadPolicy();
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }

    /**
     * SEARCH  /_search/tb-activity-types?query=:query : search for the tBActivityType corresponding
     * to the query.
     *
     * @param query the query of the tBActivityType search
     * @param pageable the pagination information
     * @return the result of the search
     */
    @GetMapping("/_search/tb-activity-types")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> searchTBActivityTypes(@RequestParam String query, Pageable pageable) {
        log.debug("REST request to search for a page of TBActivityTypes for query {}", query);
        Page<TBActivityTypeDTO> page = tBActivityTypeQueryService.searchTBActivityType(query, pageable);
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        if (currentUser.getCustomerId() != null) {
            List<String> listActivityTypeIsAssignedName = tbCropService.getListActivityTypeNameByByCustomerAndCropType(currentUser.getCustomerId(),null);
            List<TBActivityTypeDTO> tBActivityTypeDTOs = page.getContent().stream()
                .filter(item -> listActivityTypeIsAssignedName.contains(item.getName()))
                .collect(Collectors.toList());
            page = pageableUtil.changeTBActivityTypeDTOToPageFromList(tBActivityTypeDTOs, pageable);
        }
        HttpHeaders headers = PaginationUtil.generateSearchPaginationHttpHeaders(query, page, "/api/_search/tb-activity-types");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    @GetMapping("/listAllActivityTypeOption")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> getListAllActivityTypeOption(Pageable pageable) {
        List<TBActivityTypeDTO> result = tBActivityTypeService.findAll(Pageable.unpaged()).getContent()
            .stream()
            .filter(item -> item.getParentId() == null)
            .collect(Collectors.toList());
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        if (currentUser.getCustomerId() != null) {
            List<String> listActivityTypeIsAssignedName = tbCropService.getListActivityTypeNameByByCustomerAndCropType(currentUser.getCustomerId(),null);
            if(listActivityTypeIsAssignedName.size() > 0){
                result = result.stream()
                    .filter(item -> listActivityTypeIsAssignedName.contains(item.getName()))
                    .collect(Collectors.toList());
            }
        }
        result = pageableUtil.changeTBActivityTypeDTOToPageFromList(result,pageable).getContent();
        return ResponseEntity.ok().body(result);
    }

    @GetMapping("/listActivityTypeJobInActivityOption/{parentId}")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> getListActivityTypeJobInActivityOption(@PathVariable Long parentId, Pageable pageable) {
        List<TBActivityTypeDTO> result = tBActivityTypeService.findAll(Pageable.unpaged()).getContent().stream()
            .filter(type -> type.getParentId() != null && type.getParentId().equals(parentId))
            .collect(Collectors.toList());
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        if (currentUser.getCustomerId() != null) {
            List<String> listActivityTypeIsAssignedName = tbCropService.getListActivityTypeNameByByCustomerAndCropType(currentUser.getCustomerId(),null);
            if(listActivityTypeIsAssignedName.size() > 0){
                result = result.stream()
                    .filter(item -> listActivityTypeIsAssignedName.contains(item.getName()))
                    .collect(Collectors.toList());
            }
        }
        result = pageableUtil.changeTBActivityTypeDTOToPageFromList(result,pageable).getContent();
        return ResponseEntity.ok().body(result);
    }

    @GetMapping("/display-object-param-dynamic-form/{activityTypeId}")
    @Timed
    public ResponseEntity<DisplayActivityTypeDynamicFormDTO> getDisplayActivityTypeFormDTO(@PathVariable Long activityTypeId) {
        DisplayActivityTypeDynamicFormDTO displayActivityTypeDynamicFormDTO = new DisplayActivityTypeDynamicFormDTO();

        //Get list object parameter by activity type id
        TBObjectParameterCriteria objectParameterCriteria = new TBObjectParameterCriteria();
        LongFilter activityTypeIdFilter = new LongFilter();
        activityTypeIdFilter.setEquals(activityTypeId);
        objectParameterCriteria.setActivityTypeId(activityTypeIdFilter);
        List<TBObjectParameterDTO> objectParameterDTOs = tbObjectParameterQueryService.findByCriteria(objectParameterCriteria);
        displayActivityTypeDynamicFormDTO.setObjectParameterDTOList(objectParameterDTOs);

        //Get list activity extend type by activity type id
        TBActivityExtendTypeCriteria  activityExtendTypeCriteria = new TBActivityExtendTypeCriteria();
        IntegerFilter objectTypeFilter = new IntegerFilter();
        objectTypeFilter.setEquals(TYPE_LIST.getValue());
        activityExtendTypeCriteria.setActivityTypeId(activityTypeIdFilter);
        activityExtendTypeCriteria.setObjectType(objectTypeFilter);
        List<TBActivityExtendTypeDTO> tbActivityExtendTypeDTOs = tbActivityExtendTypeQueryService.findByCriteria(activityExtendTypeCriteria);
        displayActivityTypeDynamicFormDTO.setActivityExtendTypeDTOList(tbActivityExtendTypeDTOs);

        return ResponseEntity.ok().body(displayActivityTypeDynamicFormDTO);
    }

    @GetMapping("/display-object-param-dynamic-form-guideline-details/{activityTypeId}")
    @Timed
    public ResponseEntity<DisplayActivityTypeDynamicFormDTO> getDisplayActivityTypeFormGuidelineDetailsDTO(@PathVariable Long activityTypeId) {
        DisplayActivityTypeDynamicFormDTO displayActivityTypeDynamicFormDTO = new DisplayActivityTypeDynamicFormDTO();

        //Get list object parameter by activity type id
        TBObjectParameterCriteria objectParameterCriteria = new TBObjectParameterCriteria();

        BooleanFilter isUsingGuidelineFilter = new BooleanFilter();
        isUsingGuidelineFilter.setEquals(true);

        LongFilter activityTypeIdFilter = new LongFilter();
        activityTypeIdFilter.setEquals(activityTypeId);

        objectParameterCriteria.setIsGuidelineUsing(isUsingGuidelineFilter);
        objectParameterCriteria.setActivityTypeId(activityTypeIdFilter);
        List<TBObjectParameterDTO> objectParameterDTOs = tbObjectParameterQueryService.findByCriteria(objectParameterCriteria);
        displayActivityTypeDynamicFormDTO.setObjectParameterDTOList(objectParameterDTOs);

        //Get list activity extend type by activity type id
        TBActivityExtendTypeCriteria  activityExtendTypeCriteria = new TBActivityExtendTypeCriteria();
        IntegerFilter objectTypeFilter = new IntegerFilter();
        objectTypeFilter.setEquals(TYPE_LIST.getValue());

        activityExtendTypeCriteria.setActivityTypeId(activityTypeIdFilter);
        activityExtendTypeCriteria.setIsGuidelineUsing(isUsingGuidelineFilter);
        activityExtendTypeCriteria.setObjectType(objectTypeFilter);

        List<TBActivityExtendTypeDTO> tbActivityExtendTypeDTOs = tbActivityExtendTypeQueryService.findByCriteria(activityExtendTypeCriteria);
        displayActivityTypeDynamicFormDTO.setActivityExtendTypeDTOList(tbActivityExtendTypeDTOs);

        return ResponseEntity.ok().body(displayActivityTypeDynamicFormDTO);
    }

    @GetMapping("/get-all-data-from-table-common")
    @Timed
    public ResponseEntity<List<TBActivityExtendTypeDropDownDTO>> getAllDataFromTableCommon(@RequestParam String tableName) {
        List<TBActivityExtendTypeDropDownDTO> result = tbObjectParameterQueryService.getAllDataFromTableCommon(tableName);
        return ResponseEntity.ok().body(result);
    }

    @GetMapping("/get-data-from-table-common")
    @Timed
    public ResponseEntity<List<TBActivityExtendTypeDropDownDTO>> getDataFromTableCommon(@RequestParam String tableName, @RequestParam String condition) {
        List<TBActivityExtendTypeDropDownDTO> result = tbObjectParameterQueryService.getDataFromTableCommon(tableName,condition);
        return ResponseEntity.ok().body(result);
    }

    @GetMapping("/listActivityTypesCulture/{cropTypeId}")
    @Timed
    public ResponseEntity<List<TBActivityTypeDTO>> getListActivityTypesCulture(@PathVariable Long cropTypeId, Pageable pageable) {
        List<TBActivityTypeDTO> result = new ArrayList<>();
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Optional<TBCropTypeDTO> tbCropTypeDTOOptional = tbCropTypeService.findOne(cropTypeId);
        if(!tbCropTypeDTOOptional.isPresent()){
            throw new BadRequestAlertException("1048", ENTITY_NAME, "1048");
        }
        List<String> listActivityTypeIsAssignedName = tbCropService.getListActivityTypeNameByByCustomerAndCropType(currentUser.getCustomerId(),cropTypeId);
        if(listActivityTypeIsAssignedName.size() > 0){
            result = tBActivityTypeService.findAll(Pageable.unpaged()).getContent();
        }
        result = result.stream()
            .filter(item -> cropTypeId != null && listActivityTypeIsAssignedName.contains(item.getName()))
            .collect(Collectors.toList());
        result = pageableUtil.changeTBActivityTypeDTOToPageFromList(result,pageable).getContent();
        return ResponseEntity.ok().body(result);
    }

    @GetMapping("/get-all-units")
    @Timed
    public ResponseEntity<List<TBActivityTypeUnitDTO>> getAllUnits() {
        List<TBActivityTypeUnitDTO> tbActivityTypeUnitDTOs = new ArrayList<>();
        List<Constants.UNITS> strUnits = Arrays.asList(Constants.UNITS.values());
        for(Constants.UNITS unit : strUnits) {
            TBActivityTypeUnitDTO tbActivityTypeUnitDTO = new TBActivityTypeUnitDTO();
            tbActivityTypeUnitDTO.setUnitKey(unit.name());
            tbActivityTypeUnitDTO.setUnitValue(unit.getValue());
            tbActivityTypeUnitDTOs.add(tbActivityTypeUnitDTO);
        }
        return ResponseEntity.ok().body(tbActivityTypeUnitDTOs);
    }
}
