package com.oguerreiro.resilient.web.rest;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;

import com.oguerreiro.resilient.activity.Activity;
import com.oguerreiro.resilient.activity.ActivityRegistry;
import com.oguerreiro.resilient.activity.ActivityResult;
import com.oguerreiro.resilient.activity.registry.ActivityProgressDescriptor;
import com.oguerreiro.resilient.activity.registry.ActivityProgressRegistry;
import com.oguerreiro.resilient.service.dto.activity.ActivityInfoDTO;
import com.oguerreiro.resilient.service.dto.activity.ActivityInvokeDTO;
import com.oguerreiro.resilient.service.dto.activity.ActivityInvokeResponseDTO;
import com.oguerreiro.resilient.service.dto.activity.ActivityProgressDTO;
import com.oguerreiro.resilient.service.mapper.ActivityProgressMapper;

import tech.jhipster.web.util.HeaderUtil;
import tech.jhipster.web.util.ResponseUtil;

/**
 * REST controller for managing {@link com.oguerreiro.resilient.domain.Organization}.
 */
@RestController
@RequestMapping("/api/activity-engines")
public class ActivityEngineResource {

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

    private static final String ENTITY_NAME = "activity-engines";

    @Value("${jhipster.clientApp.name}")
    private String applicationName;

    private final ActivityRegistry activityRegistry;
    private final ActivityProgressRegistry activityProgressRegistry;
    private final ActivityProgressMapper activityProgressMapper;
    
    public ActivityEngineResource(ActivityProgressRegistry activityProgressRegistry, ActivityProgressMapper activityProgressMapper, ActivityRegistry activityRegistry) {
        this.activityProgressRegistry = activityProgressRegistry;
        this.activityProgressMapper = activityProgressMapper;
        this.activityRegistry = activityRegistry;
    }

    /**
     * {@code GET  /activity-engines/progress/:activityRegistryKey} 
     *
     * @param activityRegistryKey the key of the Entity to search for within the progress registry.
     * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the activityProgressDTO, or with status {@code 404 (Not Found)}.
     */
    @GetMapping("/progress/{activityRegistryKey}")
    public ResponseEntity<ActivityProgressDTO> getProgress(
    		@PathVariable("activityRegistryKey") String activityRegistryKey) 
    {
        log.debug("REST request to get Activity progress : {}", activityRegistryKey);
        
        ActivityProgressDescriptor descriptor = activityProgressRegistry.progressOf(activityRegistryKey);
        
        ActivityProgressDTO dto = activityProgressMapper.toDto(descriptor);
        if (dto == null) {
        	// Always return a progress
        	dto = new ActivityProgressDTO();
        	dto.setProgressPercentage(-1);		// Means that at this moment nothing is in progress for this Entity domain
        } 
        return ResponseUtil.wrapOrNotFound(Optional.of(dto));
    }
    
    @GetMapping("/activity/{class}/{state}")
    public ResponseEntity<List<ActivityInfoDTO>> getActivity(
    		@PathVariable("class") String activityDomainClass,
    		@PathVariable("state") String activityDomainState) 
    {
        log.debug("REST request to get Activity info : {}", activityDomainClass, activityDomainState);
        
        Map<String, Activity> activities = activityRegistry.findActivitiesFor(activityDomainClass, activityDomainState);
        List<ActivityInfoDTO> response = new ArrayList<ActivityInfoDTO>();
        for (String uuid : activities.keySet()) {
			response.add(new ActivityInfoDTO(uuid));
		}
        
        return ResponseEntity.ok().body(response);  
    }
    
    @PutMapping("/activity")
    public ResponseEntity<ActivityInvokeResponseDTO> doActivity(
    		@RequestBody ActivityInvokeDTO activityInvokeDTO) 
    {
        log.debug("REST request to get doActivity : {}", activityInvokeDTO);
        
        //Get the activity by UUID
        Activity activity = activityRegistry.getActivity(activityInvokeDTO.getActivityKey(), activityInvokeDTO.getActivityDomainClass());
        
        //Execute activity
        ActivityResult ar = activity.doActivity(activityInvokeDTO.getActivityDomainClass(), activityInvokeDTO.getActivityDomainId());
        
        ActivityInvokeResponseDTO responseDto = new ActivityInvokeResponseDTO();
        responseDto.setActivityUUID(activityInvokeDTO.getActivityKey());
        
        return ResponseEntity.ok()
                .headers(HeaderUtil.createAlert(applicationName, "Activity has started ...", activityInvokeDTO.getActivityDomainClass()))
                .body(responseDto);
    }
}
