/**
 * Copyright (c) 2021,Zhejiang @hua
 * All rights reserved.
 *
 * file name:SDKBase.cs
 *
 * version:1.0
 * author:27401
 * date:2021-6-18
 * history:create
*/

using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.Net;
using System.IO;
using DPSDK_RES = System.Int32;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Reflection;

namespace DPSDK_CSharpDemo
{
    
    class SDKBase
    {

        /* Common request platform interface,V7 version protocol
         * baseReq  request parameter
         * req      request body
         * resp     response body
         */
        public static int RequestV7<T1, T2>(ref BaseRequest baseReq, ref T1 req, ref T2 resp)
        {
            string strJsonReq = "";
            if (!baseReq.bEmptyBody)
            {
                strJsonReq = JsonSerializer<T1>(req);
            }
            string strJsonResp = "";
            int iRet = SendToServer(ref baseReq, ref strJsonReq, ref strJsonResp);
            if (strJsonResp.Length > 0)
            {
                resp = JsonDeseralize<T2>(strJsonResp);
            }
            return iRet;
        }

        /* Common request platform interface,V8 version protocol
        * baseReq  request parameter
        * req      request body
        * resp     response body
        */
        public static int RequestV8<T1, T2, T3>(ref BaseRequest baseReq, ref BaseProV8Request<T1, T2> req, ref T3 resp)
        {
            baseReq.bHeadToken = true;
            string strJsonReq = "";
            if (!baseReq.bEmptyBody)
            {
                strJsonReq = JsonSerializer<T2>(req.data);
            }
            if (!baseReq.bEmptyUrlParam)
            {
                baseReq.strUri += FormatUrlParam<T1>(req.urlParam);
            }
            string strJsonResp = "";
            int iRet = SendToServer(ref baseReq, ref strJsonReq, ref strJsonResp);
            if (strJsonResp.Length > 0)
            {
                resp = JsonDeseralize<T3>(strJsonResp);
            }
            return iRet;
        }

        /* Get user token*/
        public static string GetToken()
        {
            CSharpDemo.DPSDK_CHAR256 pBuf = new CSharpDemo.DPSDK_CHAR256();
            DPSDK_RES iRet = CSharpDemo.DPSDK_GetUserToken(AppData.m_stuLoginInfo.m_iSessionID, ref pBuf, 256);
            if (iRet == CSharpDemo.DPSDK_SUCCESS)
            {
                return pBuf.szMsg;
            }
            else
            {
                return "";
            }
        }

        /* Send message to server*/
        private static int SendToServer(ref BaseRequest baseReq, ref string strReq, ref string strResp)
        {
            HttpWebRequest hwRequest = null;
            HttpWebResponse hwResponse = null;
            strResp = string.Empty;
            try
            {
                string strUrl = string.Empty;
                if (AppData.m_stuLoginInfo.bSSLEnable)
                {
                    strUrl = "https://";
                }
                else
                {
                    strUrl = "http://";
                }
                strUrl = strUrl + AppData.m_stuLoginInfo.strIP + ":" + AppData.m_stuLoginInfo.iPort + baseReq.strUri;

                if (AppData.m_stuLoginInfo.bSSLEnable)
                {
                    ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    hwRequest = (HttpWebRequest)WebRequest.Create(strUrl);
                    hwRequest.ProtocolVersion = HttpVersion.Version10; 
                }
                else
                {
                    hwRequest = (HttpWebRequest)WebRequest.Create(strUrl);
                }
                 
                hwRequest.Timeout = baseReq.iTimeout;
                hwRequest.Method = baseReq.strMethod;
                hwRequest.ContentType = "application/json;charset=UTF-8";
                hwRequest.KeepAlive = true;
                hwRequest.Headers.Add("Accept-Language: en");
                if (baseReq.bHeadToken)
                {
                    hwRequest.Headers.Add("X-Subject-Token: " + GetToken());
                }
                hwRequest.ContentLength = 0;

                if (strReq.Length > 0)
                {
                    hwRequest.ContentLength = strReq.Length;
                    Stream postStream = hwRequest.GetRequestStream();
                    postStream.Write(Encoding.UTF8.GetBytes(strReq), 0, strReq.Length);
                }
            }
            catch (System.Exception /*err*/)
            {
                return -1;
            }
            try
            {
                hwResponse = (HttpWebResponse)hwRequest.GetResponse();
                StreamReader srReader = new StreamReader(hwResponse.GetResponseStream(), Encoding.UTF8);
                strResp = srReader.ReadToEnd();
                srReader.Close();
                hwResponse.Close();
            }
            catch (System.Exception /*err*/)
            {
                return -1;
            }
            return 0;
        }

        /* Json structure to string*/
        private static string JsonSerializer<T>(T t)
        {
            string strJson = JsonConvert.SerializeObject(t, Formatting.None);
            return strJson;
        }

        /* Json string to structure*/
        private static T JsonDeseralize<T>(string strJson)
        {
            T obj = JsonConvert.DeserializeObject<T>(strJson); ;
            return obj;
        }

        /* SSL callback*/
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //accept  
        }

        /* Format URL parameter*/
        private static String FormatUrlParam<T>(T t)
        {
            String strUrlParam = "";
            FieldInfo[] fieldInfos = t.GetType().GetFields();
            int iParamNum = 0;
            foreach (FieldInfo field in fieldInfos)
            {
                if (iParamNum > 0)
                {
                    strUrlParam += "&";
                }
                iParamNum++;
                strUrlParam += string.Format("{0}={1}", field.Name, field.GetValue(t));
            }
            return strUrlParam;
        }
 
    }
}
