package org.ut.cmldep;

import org.cloudml.codecs.JsonCodec;
import org.cloudml.codecs.commons.Codec;
import org.cloudml.core.Deployment;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jettison.json.JSONException;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.*;
import org.ut.cmldep.json.parser.InstancesToDelete;
import org.ut.cmldep.json.parser.NewConfiguration;

import javax.ws.rs.core.Response;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("/rest")
@EnableGlobalMethodSecurity(securedEnabled = false)

public class RESTController {

    private final ExperimentExecutor experimentExecutor = new ExperimentExecutor();


    /*@RequestMapping(method=RequestMethod.GET)
    public Answer getClichedMessage() throws JSONException {
    	
    	if(CMLDeployer.getSingleton().start()){
    		return new Answer("Done");
    	}else{
    		return new Answer("Error");
    	}
    }*/

    @RequestMapping(method=RequestMethod.GET)
    public Answer test() throws JSONException {

        return new Answer("Hello world )");
    }

    @RequestMapping(value="/initial",method=RequestMethod.GET)
    public Answer startInitialConfig() throws JSONException {

        CMLDeployer.getSingleton().startInitialSetUp();

        return new Answer("Initial ready");
    }

    @RequestMapping(value="/start",method=RequestMethod.GET)
    public Answer startInitialWithLBConfig() throws JSONException {

        CMLDeployer.getSingleton().startExperiment();

        return new Answer("Initial ready");
    }

    @RequestMapping(value="/test/up", method=RequestMethod.GET)
    public Answer configureForExperimentUp(
            @RequestParam(value = "config") String config
    ) throws JSONException {

        String[] configuration = config.split(",");
        int[] realConfig = new int[configuration.length];

        for(int i = 0;i < configuration.length;i++){
            realConfig[i] = Integer.parseInt(configuration[i]);
        }

        CMLDeployer.getSingleton().scaleUpTest(realConfig);

        return new Answer("Test up, finished");
    }

    @RequestMapping(value="/test/down", method=RequestMethod.GET)
    public Answer configureForExperimentDown(
            @RequestParam(value = "config") String config
    ) throws JSONException {

        String[] configuration = config.split(",");
        int[] realConfig = new int[configuration.length];

        for(int i = 0;i < configuration.length;i++){
            realConfig[i] = Integer.parseInt(configuration[i]);
        }

        CMLDeployer.getSingleton().scaleDownTest(realConfig);

        return new Answer("Test down, finished");
    }


    @RequestMapping(value="/experiment", method=RequestMethod.GET)
    public Answer configureForExperiment(
            @RequestParam(value = "period") int period,
            @RequestParam(value = "delay") int delay
    ) throws JSONException {

        this.experimentExecutor.start(period, delay, "experiment_1");
        return new Answer("Experiment finished");
    }


    @RequestMapping(value="/experiment/continue", method=RequestMethod.GET)
    public Answer continueExperiment(
            @RequestParam(value = "period") int period,
            @RequestParam(value = "delay") int delay
    ) throws JSONException {

        this.experimentExecutor.start(period, delay, "newTest");
        return new Answer("Hello I am here");
    }

    @RequestMapping(value="/model", method=RequestMethod.GET)
    public Response continueExperiment(
    ) throws JSONException {


        Codec jsonCodec = new JsonCodec();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        jsonCodec.save((Deployment) CMLDeployer.getSingleton().getModel(), stream);

        return Response.ok().entity(stream.toByteArray()).build();
    }

    @RequestMapping(value="/instance/up", method=RequestMethod.GET)
    public Answer startExperiment(@RequestParam(value = "type") String type) throws JSONException {

        CMLDeployer.getSingleton().scaleUp(type);
        return new Answer("Hello I am here");
    }

    @RequestMapping(value="/instance/down", method=RequestMethod.GET)
    public Answer stopExperiment(@RequestParam(value = "type") String type) throws JSONException {

        CMLDeployer.getSingleton().scaleDown(type);
        return new Answer("Hello I am here");
    }

    @RequestMapping(method=RequestMethod.PUT)
    public Answer changeConfig(@RequestBody String json) throws IOException {

    	ObjectMapper mapper = new ObjectMapper();
        JsonNode actualObj = mapper.readTree(json);
        
        NewConfiguration config = new NewConfiguration(actualObj);

        CMLDeployer.getSingleton().scaleUp(config);

        return new Answer("Done");
    }

    @RequestMapping(method=RequestMethod.DELETE)
    public Answer killInstances(@RequestBody String json) throws IOException {
    	
    	ObjectMapper mapper = new ObjectMapper();
        JsonNode actualObj = mapper.readTree(json);
        
    	List<String> list = new InstancesToDelete(actualObj).getInstances();

        CMLDeployer.getSingleton().scaleDown(list);

    	return new Answer("Done");
    }
}
