using System;
using System.Collections.Generic;
using System.Threading;
using ChuPiao.Common.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using log4net;
using ChuPiao.Common.Communication.GtdJson.Packs;
using System.Text;
using System.IO;
using System.Net;

namespace ChuPiao.Common.Communication.GtdJson
{
    /// <summary>
    /// 出票点通讯包管理器
    /// </summary>
    public class PackManager
    {
        public static PackManager Instance=new PackManager();

        public PackManager()
        {
            //PackSettings.Instance.Configure();
            _log=LogManager.GetLogger("default");
        }

        /// <summary>
        /// 密钥
        /// </summary>
        private string _userKey = null;
        public string UserKey
        {
            get { return _userKey; }
            set { _userKey = value; }
        }

        private ILog _log;
        public ILog Log
        {
            get { return _log; }
            set { _log = value; }
        }


        private long _messageId = 1000000;
        /// <summary>
        /// 消息ID
        /// </summary>
        public string GetMessageId()
        {
            long result = ++_messageId;
            return result.ToString();
        }

        public PackRetBase Send(PackBase pack)
        {
            pack.MessageId = GetMessageId();
            pack.Timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            string strPack = pack.Pack();
            //_log.Debug(string.Format("发送：【{0}】", strPack));
            string retData = "";

            int retry = 0;
            while (true)
            {
                try
                {
                    string postData = string.Concat("msg=", System.Web.HttpUtility.UrlEncode(strPack, Encoding.GetEncoding("utf-8")));
                    //string postData = string.Concat("msg=", strPack);
                    retData = this.Post(string.Format(PackSetting.Instance.Url, pack.Action), postData, "application/x-www-form-urlencoded", Encoding.GetEncoding("utf-8"), PackSetting.Instance.TimeOut);
                    //_log.Debug(string.Format("返回：【{0}】", retData.TrimEnd(new char[] { (char)13, (char)10 })));

                    if (retry > 0)
                    {
                        _log.Info(string.Format("网络异常重试第 {0} 次，成功！", retry + 1));
                    }
                    break;
                }
                catch (Exception exception)
                {
                    retry++;
                    if (retry == 6)
                    {
                        string strMsg = string.Concat("接口发送数据异常（已尝试6次），接口：", pack.Action, " 异常信息：", exception.Message);
                        _log.Error(exception.ToString());
                        throw new Exception(strMsg);
                    }
                    else
                    {
                        _log.Info("网络异常第 " + retry.ToString() + " 次，将重试...\n" + exception.ToString());
                        Thread.Sleep(retry * 5000);
                    }
                }
            }

            PackRetBase retpack = CreateRetPack(pack.Action);
            retpack.Salt = pack.Salt;
            retpack.UnPack(retData);
            return retpack;
        }

        public string Post(string url, string postData, string contentType, Encoding encoding, int timeout)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            byte[] data = encoding.GetBytes(postData);
            // 准备请求... 
            try
            {
                // 设置参数 

                request = WebRequest.Create(url) as HttpWebRequest;
                //CookieContainer cookieContainer = new CookieContainer();
                //request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.ContentType = contentType;
                //request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                request.Headers.Add("charset", "utf-8");
                request.Timeout = timeout;
                DateTime t1 = DateTime.Now;
                outstream = request.GetRequestStream();
                //_log.Debug(string.Concat("request.GetRequestStream() cost:", DateTime.Now.Subtract(t1).TotalMilliseconds));
                t1 = DateTime.Now;
                outstream.Write(data, 0, data.Length);
                //_log.Debug(string.Concat("outstream.Write() cost:", DateTime.Now.Subtract(t1).TotalMilliseconds));
                outstream.Close();
                //outstream = null;
                //发送请求并获取相应回应数据 
                response = request.GetResponse() as HttpWebResponse;
                sr = new StreamReader(response.GetResponseStream(), encoding);
                //返回结果网页（html）代码 
                string content = sr.ReadToEnd();
                return content;
            }
            catch (Exception ex)
            {
                throw ex;
                return string.Empty;
            }
            finally
            {
                if (request != null)
                {
                    request.Abort();
                    request = null;
                }
                if (response != null)
                {
                    response.Close();
                    response = null;
                }
                if (outstream != null)
                {
                    outstream.Close();
                    outstream = null;
                }
                if (instream != null)
                {
                    instream.Close();
                    instream = null;
                }
                if (sr != null)
                {
                    sr.Close();
                    sr = null;
                }
            }
        }
        
        /// <summary>
        /// 根据包命令号创建一个回复包对象
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public PackRetBase CreateRetPack(string action)
        {
            PackRetBase packBase = null;
            switch (action)
            {
                case "getTicket":
                    packBase = new A10001GetTicketRet();
                    break;
                case "notifyTicket":
                    packBase = new A10002NotifyTicketRet();
                    break;
                case "getBonus":
                    packBase = new A10003GetBonusRet();
                    break;
                case "getSales":
                    packBase = new A10004GetSalesRet();
                    break;
                case "uploadReport":
                    packBase = new A10005UploadMachineSaleRet();
                    break;
                case "uploadBalance":
                    packBase = new A10006UploadMachineBalanceRet();
                    break;
                case "uploadPayment":
                    packBase = new A10007UploadMachinePayRet();
                    break;
                case "notifyOpencode":
                    packBase = new A10008UploadOpenCodeRet();
                    break;
                case "getCommand":
                    packBase = new A10009GetCommandRet();
                    break;
                case "notifyBonusTicket":
                    packBase = new A10010NotifyBonusRet();
                    break;
                default:
                    throw new Exception(string.Format("未知action：{0}", action));
            }
            return packBase;
        }
    }
}
