import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

/**
 * @author couedrao on 27/11/2019.
 * @project gctrl
 */
class SDNCtrlAPI {

    String redirect_traffic(String olddestip, String newdestip) throws ClientProtocolException, IOException{
        String status = "OK";
        Main.logger(this.getClass().getSimpleName(), "olddestip = " + olddestip + "; newdestip = " + newdestip);
        
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost;
        String match, actions, inputJson, line;
        StringEntity stringEntity;
        HttpResponse response;
        BufferedReader br;
        StringBuffer result;
        
        
        //On s3: Redirect traffic from gwf2 to gwi2 through s4
		httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_src\": \"10.0.2.100\"\n" +
                "}";
        actions = "[\n" +
                "  {\"type\": \"SET_FIELD\", \"field\":\"eth_dst\", \"value\":\"00:00:00:00:00:20\"}, \n" +
                "  {\"type\": \"SET_FIELD\", \"field\":\"ipv4_dst\", \"value\":\"10.2.2.2\"}, \n" +
                "  {\"type\": \"OUTPUT\", \"port\":2} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 3,\n" +
                "  \"priority\": 1,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        //On s3: Redirect traffic from gwf3 to gwi2 through s4
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_src\": \"10.0.3.100\"\n" +
                "}";
        actions = "[\n" +
                "  {\"type\": \"SET_FIELD\", \"field\":\"eth_dst\", \"value\":\"00:00:00:00:00:20\"}, \n" +
                "  {\"type\": \"SET_FIELD\", \"field\":\"ipv4_dst\", \"value\":\"10.2.2.2\"}, \n" +
                "  {\"type\": \"OUTPUT\", \"port\":2} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 3,\n" +
                "  \"priority\": 1,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        //On s3: Redirect traffic from gwf1 to gwi1 through s2
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_src\": \"10.0.1.100\"\n" +
                "}";
        actions = "[\n" +
                "  {\"type\": \"OUTPUT\", \"port\":1} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 3,\n" +
                "  \"priority\": 1,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        
        //On s4: Redirect traffic from s3 to gwi2
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"in_port\": 1,\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_dst\": \"10.2.2.2\"\n" +
                "}";
        actions = "[\n" +
                "  {\"type\": \"OUTPUT\", \"port\":2} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 4,\n" +
                "  \"priority\": 1,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        //On s4: Redirect traffic from gwf3 to gwi2
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_src\": \"10.0.3.100\"\n" +
                "}";
        actions = "[\n" +
        		"  {\"type\": \"SET_FIELD\", \"field\":\"eth_dst\", \"value\":\"00:00:00:00:00:20\"}, \n" +
                "  {\"type\": \"SET_FIELD\", \"field\":\"ipv4_dst\", \"value\":\"10.2.2.2\"}, \n" +
                "  {\"type\": \"OUTPUT\", \"port\":2} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 4,\n" +
                "  \"priority\": 1,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        return status;
    }

    String insert_a_loadbalancer(String oldgwip, String lbip, List<String> newgwsip) {
        String status = "OK";
        Main.logger(this.getClass().getSimpleName(), "oldgwip = " + oldgwip + "; lbip = " + lbip + "; newgwsip = " + newgwsip);
        //TODO

        return status;
    }

    String remove_less_important_traffic(String importantsrcip) throws ClientProtocolException, IOException{
        String status = "OK";
        
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost;
        String match, actions, inputJson, line;
        StringEntity stringEntity;
        HttpResponse response;
        BufferedReader br;
        StringBuffer result;
        
        Main.logger(this.getClass().getSimpleName(), "importantsrcip = " + importantsrcip);
        
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048,\n" +
                "  \"ipv4_src\": \""+importantsrcip+"\"\n" +
                "}";
        actions = "[\n" +
        		"  {\"type\": \"OUTPUT\", \"port\":1} \n" +
                "]";
        inputJson = "{\n" +
                "  \"dpid\": 3,\n" +
                "  \"priority\": 3,\n" +
                "  \"match\": "+match+",\n" +
                "  \"actions\": "+actions+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }
        
        httpPost = new HttpPost("http://127.0.0.1:8080/stats/flowentry/add");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");//vnfinfos.get("image")
        match = "{\n" +
                "  \"ipv4_dst\": \"10.2.2.1\",\n" +
                "  \"eth_type\": 2048\n" +
                "}";
        inputJson = "{\n" +
                "  \"dpid\": 3,\n" +
                "  \"priority\": 2,\n" +
                "  \"match\": "+match+"\n" +
                "}";
        stringEntity = new StringEntity(inputJson);
        httpPost.setEntity(stringEntity);
        response = httpclient.execute(httpPost);
        br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }
        result = new StringBuffer();
        line = "";
        while ((line = br.readLine()) != null) {
            System.out.println("Response : \n" + result.append(line));
        }

        return status;
    }


}
