package io.renren.common.utils;

import com.alibaba.fastjson.JSONObject;
import io.argoproj.workflow.ApiException;
import io.argoproj.workflow.Configuration;
import io.argoproj.workflow.JSON;
import io.argoproj.workflow.apis.WorkflowServiceApi;
import io.argoproj.workflow.apis.WorkflowTemplateServiceApi;
import io.argoproj.workflow.models.*;
import lombok.extern.slf4j.Slf4j;

import io.argoproj.workflow.ApiClient;
//import org.apache.http.client.HttpClient;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.protocol.Protocol;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * Argo 工具
 * @author Zhang
 * @version 3.0.0
 * @since JDK1.8
 */
@Slf4j
public class ArgoUtils {

    private static ApiClient apiClient;
    private static String basepath;
    private static String minioendpoint;
    private static String minioAccesskey;
    private static String minioSecretkey;

    private static String sparkMasterRest;
    private static String sparkMaster;
    private static String sparkHdfsurl;
    private static String sparkYarnAddress;
    private static String sparkYarnJARS;
//    private static MinioClient minioClient;
//    private static String endpoint;
//    private static String accessKey;
//    private static String secretKey;

    /**
     * 无参构造函数
     */
    public ArgoUtils() {
    }

    /**
     * 构造函数
     * @param basepath Argo访问地址
     * @param minioendpoint Argo内Minio访问地址
     * @param minioAccesskey Minio Accesskey
     * @param minioSecretkey Minio Secretkey
     * @param sparkMasterRest Spark Rest方式访问地址
     * @param sparkMaster Spark访问地址
     * @param sparkHdfsurl 与spatk关联的Hdfs访问地址
     */
    public ArgoUtils(String basepath, String minioendpoint, String minioAccesskey, String minioSecretkey,String sparkMasterRest,String sparkMaster,String sparkHdfsurl,String sparkYarnAddress, String sparkYarnJARS) {
        ArgoUtils.basepath = basepath;
        ArgoUtils.minioendpoint = minioendpoint;
        ArgoUtils.minioAccesskey = minioAccesskey;
        ArgoUtils.minioSecretkey = minioSecretkey;

        ArgoUtils.sparkMasterRest = sparkMasterRest;
        ArgoUtils.sparkMaster = sparkMaster;
        ArgoUtils.sparkHdfsurl = sparkHdfsurl;
        ArgoUtils.sparkYarnAddress = sparkYarnAddress;
        ArgoUtils.sparkYarnJARS = sparkYarnJARS;
        createArgoApiClient();
    }

    public static ApiClient getApiClient() {
        return apiClient;
    }

    public static void setApiClient(ApiClient apiClient) {
        ArgoUtils.apiClient = apiClient;
    }

    public static String getBasepath() {
        return basepath;
    }

    public static void setBasepath(String basepath) {
        ArgoUtils.basepath = basepath;
    }
    public static String getMinioendpoint() {
        return minioendpoint;
    }

    public static void setMinioendpoint(String minioendpoint) {
        ArgoUtils.minioendpoint = minioendpoint;
    }

    public static String getMinioAccesskey() {
        return minioAccesskey;
    }

    public static void setMinioAccesskey(String minioAccesskey) {
        ArgoUtils.minioAccesskey = minioAccesskey;
    }

    public static String getMinioSecretkey() {
        return minioSecretkey;
    }

    public static void setMinioSecretkey(String minioSecretkey) {
        ArgoUtils.minioSecretkey = minioSecretkey;
    }

    public static String getSparkMasterRest() {
        return sparkMasterRest;
    }

    public static void setSparkMasterRest(String sparkMasterRest) {
        ArgoUtils.sparkMasterRest = sparkMasterRest;
    }

    public static String getSparkMaster() {
        return sparkMaster;
    }

    public static void setSparkMaster(String sparkMaster) {
        ArgoUtils.sparkMaster = sparkMaster;
    }

    public static String getSparkHdfsurl() {
        return sparkHdfsurl;
    }

    public static void setSparkHdfsurl(String sparkHdfsurl) {
        ArgoUtils.sparkHdfsurl = sparkHdfsurl;
    }

    public static String getSparkYarnAddress() {
        return sparkYarnAddress;
    }

    public static void setSparkYarnAddress(String sparkYarnAddress) {
        ArgoUtils.sparkYarnAddress = sparkYarnAddress;
    }

    public static String getSparkYarnJARS() {
        return sparkYarnJARS;
    }

    public static void setSparkYarnJARS(String sparkYarnJARS) {
        ArgoUtils.sparkYarnJARS = sparkYarnJARS;
    }

    /**
     * Description 创建minIOClient
     */
    public void createArgoApiClient(){

//        ApiClient defaultClient = Configuration.getDefaultApiClient();
//        defaultClient.setBasePath("http://192.168.222.100:32639");
////        defaultClient.setBasePath("https://150.158.138.99:31547");
////        defaultClient.setBasePath("https://182.92.79.148:31828");
//        defaultClient.setVerifyingSsl(false);
//
//        apiClient = defaultClient;

        apiClient = Configuration.getDefaultApiClient();
        apiClient.setBasePath(basepath);
        apiClient.setVerifyingSsl(false);
        //获取日志部分
        JSON json = new JSON().setLenientOnJson(true);
        apiClient.setJSON(json);

    }

    /**
     * 创建workflowTemplate
     * @param namespace 命名空间
     * @param body workflowTemplate创建请求体
     * @return 创建好的workflowTemplate
     * @throws ApiException workflowTemplate创建请求体不规范时
     */
    public static WorkflowTemplate createWorkflowTemplate(String namespace,WorkflowTemplateCreateRequest body) throws ApiException {
        WorkflowTemplateServiceApi apiInstance = new WorkflowTemplateServiceApi(apiClient);
        return apiInstance.workflowTemplateServiceCreateWorkflowTemplate(namespace, body);
    }

    /**
     * 根据创建好的workflow 提交workflow
     * @param namespace 命名空间
     * @param body workflow提交请求体
     * @return 提交成功的workflow
     * @throws ApiException  workflow提交请求体不规范时
     */
    public static Workflow submitWorkflow(String namespace, WorkflowSubmitRequest body) throws ApiException {
        WorkflowServiceApi workflowServiceApi = new WorkflowServiceApi(apiClient);
        return workflowServiceApi.workflowServiceSubmitWorkflow(namespace, body);
    }

    /**
     * 根据工作流名称获取工作流
     * @param namespace 命名空间
     * @param workflowname workflow名称
     * @return 获取到的工作流
     * @throws ApiException api访问异常
     */
    public static Workflow getWorkflow(String namespace,String workflowname) throws ApiException {
        WorkflowServiceApi apiInstance = new WorkflowServiceApi(apiClient);
        return apiInstance.workflowServiceGetWorkflow(namespace, workflowname, null, null);
    }

    /**
     * 根据工作流名称获取工作流状态
     * @param namespace 命名空间
     * @param workflowname workflow名称
     * @return 获取到的工作流
     * @throws ApiException api访问异常
     */
    public static String getWorkflowStatus(String namespace,String workflowname) throws ApiException {
        WorkflowServiceApi apiInstance = new WorkflowServiceApi(apiClient);
        Workflow workflow = apiInstance.workflowServiceGetWorkflow(namespace, workflowname, null, null);
        return workflow.getStatus().getPhase();
    }

    /**
     * 根据工作流名称获取工作流
     * @param namespace 命名空间
     * @param workflowname workflow名称
     * @return 获取到的工作流
     * @throws ApiException api访问异常
     */
    public static String getWorkflowlog(String namespace,String workflowname,String containertype) throws Exception {
//        WorkflowServiceApi apiInstance = new WorkflowServiceApi(apiClient);
//        return apiInstance.workflowServiceGetWorkflow(namespace, workflowname, null, null);

        String getlogurl = basepath+"/api/v1/workflows/"+namespace+"/"+workflowname+"/log?logOptions.container="+containertype+"&logOptions.follow=true";
//        String response = doGet("https://42.192.195.253:31691/api/v1/workflows/argo/algorithm-visual-2rqhq/log?logOptions.container=wait&logOptions.follow=true", "GBK");
        System.out.println(getlogurl);
        String response = doGet(getlogurl, "GBK");
//        System.out.println("---------------------切分");
        StringBuilder sblog = new StringBuilder();

        if(!response.equals("")){
            String[] split = response.split("\\r?\\n");
            for(String strsplit:split){
                JSONObject parse = com.alibaba.fastjson.JSON.parseObject(strsplit);
                System.out.println(parse.toString());
                JSONObject result = parse.getJSONObject("result");
                System.out.println(result.getString("podName"));
                System.out.println(result.getString("content"));
                sblog.append(result.getString("podName")+": "+result.getString("content"));
                sblog.append("\n");
            }
        }

        return sblog.toString();
    }

    /**
     * 根据工作流名称获取工作流
     * @param namespace 命名空间
     * @param workflowname workflow名称
     * @return 获取到的工作流
     * @throws ApiException api访问异常
     */
    public static String getpodlog(String namespace,String workflowname,String containertype,String podname) throws Exception {
//        WorkflowServiceApi apiInstance = new WorkflowServiceApi(apiClient);
//        return apiInstance.workflowServiceGetWorkflow(namespace, workflowname, null, null);

        String getlogurl = basepath+"/api/v1/workflows/"+namespace+"/"+workflowname+"/log?logOptions.container="+containertype+"&logOptions.follow=true&podName="+podname;
//        String response = doGet("https://42.192.195.253:31691/api/v1/workflows/argo/algorithm-visual-2rqhq/log?logOptions.container=wait&logOptions.follow=true&podName=algorithm-visual-2rqhq-2795439875", "GBK");
        System.out.println(getlogurl);
        String response = doGet(getlogurl, "GBK");
//        System.out.println("---------------------切分");
        StringBuilder sblog = new StringBuilder();

        if(!response.equals("")){
            String[] split = response.split("\\r?\\n");
            for(String strsplit:split){
                JSONObject parse = com.alibaba.fastjson.JSON.parseObject(strsplit);
//                System.out.println(parse.toString());
                JSONObject result = parse.getJSONObject("result");
//                System.out.println(result.getString("podName"));
//                System.out.println(result.getString("content"));
                sblog.append(result.getString("podName")+": "+result.getString("content"));
                sblog.append("\n");
            }
        }

        return sblog.toString();
    }

    /**
     * stop  工作流 ，最终状态为failed
     * @param namespace 命名空间
     * @param workflowname workflow名称
     * @return 获取到的工作流
     * @throws ApiException api访问异常
     */
    public static String stopWorkflow(String namespace,String workflowname) throws Exception {
        WorkflowServiceApi apiInstance = new WorkflowServiceApi(apiClient);
        WorkflowStopRequest workflowStopRequest = new WorkflowStopRequest();
        Workflow workflow = apiInstance.workflowServiceStopWorkflow(namespace,workflowname,workflowStopRequest);
        System.out.println("stopworkflew: "+workflow.getStatus().getPhase());
        return workflow.getStatus().getPhase();
    }


    /**
     * httpClient的get请求方式
     * 使用GetMethod来访问一个URL对应的网页实现步骤：
     * 1.生成一个HttpClient对象并设置相应的参数；
     * 2.生成一个GetMethod对象并设置响应的参数；
     * 3.用HttpClient生成的对象来执行GetMethod生成的Get方法；
     * 4.处理响应状态码；
     * 5.若响应正常，处理HTTP响应内容；
     * 6.释放连接。
     * @param url
     * @param charset
     * @return
     */
    public static String doGet(String url, String charset) throws Exception {

        trustAllHosts();
        //1.生成HttpClient对象并设置参数
//        HttpClientFactory httpClientFactory = new HttpClientFactory();
//        org.apache.http.client.HttpClient httpClient = httpClientFactory.getHttpsClient();

        HttpClient httpClient = new HttpClient();

//        httpClient.setHostnameVerifier(DO_NOT_VERIFY)
        Protocol myhttps = new Protocol("https", new MySSLProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", myhttps);

        //设置Http连接超时为10秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
        //2.生成GetMethod对象并设置参数
        GetMethod getMethod = new GetMethod(url);

        //设置get请求超时为10秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 10000);
        //设置请求重试处理，用的是默认的重试处理：请求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
        String response = "";
        //3.执行HTTP GET 请求
        try {
            int statusCode = httpClient.executeMethod(getMethod);
            //4.判断访问的状态码
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("请求出错：" + getMethod.getStatusLine());
            }
            //5.处理HTTP响应内容
            //HTTP响应头部信息，这里简单打印
            Header[] headers = getMethod.getResponseHeaders();
//            for(Header h : headers) {
//                System.out.println(h.getName() + "---------------" + h.getValue());
//            }
            //读取HTTP响应内容，这里简单打印网页内容
            //读取为字节数组
            byte[] responseBody = getMethod.getResponseBody();

            response = new String(responseBody, charset);

        } catch (HttpException e) {
            //发生致命的异常，可能是协议不对或者返回的内容有问题
            System.out.println("请检查输入的URL!");
            e.printStackTrace();
        } catch (IOException e) {
            //发生网络异常
            System.out.println("发生网络异常!");
            e.printStackTrace();
        } finally {
            //6.释放连接
            getMethod.releaseConnection();
        }
        return response;
    }
    /**
     * Trust every server - dont check for any certificate
     */
    private static void trustAllHosts() {
        final String TAG = "trustAllHosts";
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//                Log.i(TAG, "checkClientTrusted");
            }
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//                Log.i(TAG, "checkServerTrusted");
            }
        } };
        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }





}
