using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.ProtocolBuffers;
using com.gexin.rp.sdk.dto;
using com.igetui.api.openservice;
using com.igetui.api.openservice.igetui;
using com.igetui.api.openservice.igetui.template;
using com.igetui.api.openservice.payload;
using System.Net;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Http;
using MadRunFabric.Common.Http;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Api.PushMessage.Model;
using GetuiServerApiSDK.payload;

#region 说明
// 说明：
// 此工程是一个测试工程，所用的相关.dll文件，都已经存在protobuffer文件里，需要加载到References里。
// 工程中还有用到一个System.Web.Extensions文件，这个文件是用到Framework里V4.0版本的，
//      一般路径如下：C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0，
//      或如下路径：C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5没有的也可以在protobuffer
// 文件夹里找到。如再有问题，请直接联系技术客服，谢谢！
//      GetuiServerApiSDK：此.dll文件为个推C#版本的SDK文件
// Google.ProtocolBuffers：此.dll文件为Google的数据交换格式文件
// 注：
//      新增一个连接超时时间设置，通过在环境变量--用户变量中增加名为：GETUI_TIMEOUT 的变量（修改环境变量，
//      电脑重启后才能生效），值则是超时时间，如不设定，则默认为20秒。
#endregion

namespace Api.PushMessage
{
    public class PushMessage
    {
        private static PushMessageOptions _push;

        static void Main(string[] args)
        {
            #region 获取配置文件
            IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
            #endregion
            _push = new PushMessageOptions
            {
                URL = config["PushMessageOptions:URL"].ToString(),
                HOST = config["PushMessageOptions:HOST"].ToString(),
                APPID = config["PushMessageOptions:APPID"].ToString(),
                APPKEY = config["PushMessageOptions:APPKEY"].ToString(),
                MASTERSECRET = config["PushMessageOptions:MASTERSECRET"].ToString(),
                DeviceToken = config["PushMessageOptions:DeviceToken"].ToString(),
                AppLogo = config["PushMessageOptions:AppLogo"].ToString(),
                AppLogoUrl = config["PushMessageOptions:AppLogoUrl"].ToString(),
                SleepTime = Convert.ToInt32(config["PushMessageOptions:SleepTime"])
            };

            //toList接口每个用户状态返回是否开启，可选
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            Environment.SetEnvironmentVariable("needDetails", "true");

            System.Console.WriteLine("Hello Push!");
            Thread t = new Thread(new ThreadStart(PushOut));
            t.Start();
            //Console.ReadLine();
        }

        /// <summary>
        /// 推送
        /// </summary>
        public static void PushOut()
        {
            int n = 0;
            while (true)
            {
                n += 1;
                Thread.Sleep(_push.SleepTime);
                System.Console.WriteLine(DateTime.Now.ToString() + "--" + n + "------------------------------------");
                try
                {
                    //获取app客户端clientid
                    string resultClient = HttpHelper.HttpGet(_push.URL + "messageapi/api/message/getclientidlist");
                    JObject jsonClient = (JObject)JsonConvert.DeserializeObject(resultClient);
                    //JObject jsonClient = (JObject)JsonConvert.DeserializeObject("{\"state\":\"success\",\"message\":\"没有获取到该设备clientid\",\"data\":[{\"clientid\":\"4096c06058882c2be2884d0f6c640ec5\",\"usercode\":\"8000\"}]}");
                    JArray arrayClient = (JArray)jsonClient["data"];
                    foreach (var itemClient in arrayClient)
                    {
                        Thread.Sleep(2000);
                        int apptype = Convert.ToInt32(itemClient["apptype"].ToString());   //应用分类（1android 2ios）
                        string clientid = itemClient["clientid"].ToString();  //ClientId值
                        string usercode = itemClient["usercode"].ToString();   //用户code
                        if (!string.IsNullOrEmpty(usercode))
                        {
                            //获取工单消息
                            string resultMessage = HttpHelper.HttpGet(_push.URL + "messageapi/api/message/getmessagelists?usercode=" + usercode);
                            JObject jsonMessage = (JObject)JsonConvert.DeserializeObject(resultMessage);
                            //JObject jsonMessage = (JObject)JsonConvert.DeserializeObject("{\"state\":\"success\",\"message\":\"获取成功\",\"data\":{\"rows\":[{\"id\":\"5b6d31ae8fe5b883f87da70b\",\"channelcode\":1,\"wotype\":1,\"wostate\":3,\"wocode\":\"20180810143318973\",\"proname\":\"维修工单:20180810143318973\",\"title\":\"20180810143318973\",\"checkby\":\"8000\",\"content\":\"测试添加报修工单\",\"statename\":\"已完成\",\"createby\":\"8000\",\"createtime\":\"2018-08-10 14:33:18\"},{\"id\":\"5b6d30948fe5b883f87da709\",\"channelcode\":2,\"wotype\":2,\"wostate\":0,\"wocode\":\"20180810142836032\",\"proname\":\"保养工单:20180810142836032\",\"title\":\"20180810142836032\",\"checkby\":null,\"content\":\"天都一号保养\",\"statename\":\"未完成\",\"createby\":\"8000\",\"createtime\":\"2018-08-10 14:28:36\"}],\"total\":24}}");
                            JArray arrayMessage = (JArray)jsonMessage["data"]["rows"];
                            foreach (var item in arrayMessage)
                            {
                                //内容长度,获取前40个字符的内容
                                int len = 40;
                                int content_len = item["content"].ToString().Length;
                                string contents = content_len > len ? item["content"].ToString().Substring(0, len) : item["content"].ToString();

                                string woid = item["woid"].ToString();
                                string wocode = item["wocode"].ToString();
                                int wostate = Convert.ToInt32(item["wostate"]);
                                string channelcode = item["channelcode"].ToString();
                                string title = item["proname"].ToString();  //通知栏标题
                                string text = contents;   //通知栏内容
                                string transmissiontype = "1";      //应用启动类型，1：强制应用启动  2：等待应用启动
                                string transmissioncontent = contents;    //透传内容 必须限制长度，不然会报错
                                //对指定列表用户推送 - 应用分类（1android 2ios）
                                if (apptype == 1)
                                {
                                    PushMessageToList(title, text, transmissiontype, transmissioncontent, woid, wocode, wostate, channelcode, usercode, clientid);
                                }
                                else
                                {
                                    PushMessageToSingle(title, text, transmissiontype, transmissioncontent, woid, wocode, wostate, channelcode, usercode, clientid);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message.ToString());
                }
            }
        }

        #region 消息推送的四种方式
        /// <summary>
        /// 对指定列表用户推送
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        /// <param name="transmissiontype"></param>
        /// <param name="transmissioncontent"></param>
        /// <param name="wocode"></param>
        /// <param name="channelcode"></param>
        /// <param name="usercode"></param>
        /// <param name="clientid"></param>
        private static void PushMessageToList(string title, string text, string transmissiontype, string transmissioncontent, string woid, string wocode, int wostate, string channelcode, string usercode, string clientid)
        {
            // 推送主类（方式1，不可与方式2共存）
            IGtPush push = new IGtPush(_push.HOST, _push.APPKEY, _push.MASTERSECRET);
            // 推送主类（方式2，不可与方式1共存）此方式可通过获取服务端地址列表判断最快域名后进行消息推送，每10分钟检查一次最快域名
            //IGtPush push = new IGtPush("",APPKEY,MASTERSECRET);

            ListMessage message = new ListMessage();
            NotificationTemplate template = NotificationTemplateDemo(title, text, transmissiontype, transmissioncontent);
            // 用户当前不在线时，是否离线存储,可选
            message.IsOffline = true;
            // 离线有效时间，单位为毫秒，可选
            message.OfflineExpireTime = 1000 * 3600 * 12;
            message.Data = template;
            //message.PushNetWorkType = 0;  //判断是否客户端是否wifi环境下推送，1为在WIFI环境下，0为不限制网络环境。

            //设置接收者
            List<com.igetui.api.openservice.igetui.Target> targetList = new List<com.igetui.api.openservice.igetui.Target>();

            #region 用户clientid
            //获取app客户端clientid            
            com.igetui.api.openservice.igetui.Target target = new com.igetui.api.openservice.igetui.Target();
            target.appId = _push.APPID;
            target.clientId = clientid;
            targetList.Add(target);
            #endregion

            String contentId = push.getContentId(message);
            String pushResult = push.pushMessageToList(contentId, targetList);
            #region 成功推送，记录推送消息
            JObject jsonpush = (JObject)JsonConvert.DeserializeObject(pushResult);
            if (jsonpush["result"].ToString() == "ok")
            {
                string urlsql = "?woid=" + woid + "&wocode=" + wocode + "&wostate=" + wostate + "&usercode=" + usercode + "&channelcode=" + channelcode;
                string resultaddmessage = HttpHelper.HttpGet(_push.URL + "messageapi/api/message/addappmessage" + urlsql);
                Console.WriteLine("\nSuccessfully Pushed - workorder:" + wocode+ ",usercode:" + usercode + ",clientid:" + clientid);
            }
            #endregion
            System.Console.WriteLine("The server returns the result:" + pushResult);
        }

        /// <summary>
        /// 对单个用户推送消息
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        /// <param name="transmissiontype"></param>
        /// <param name="transmissioncontent"></param>
        /// <param name="wocode"></param>
        /// <param name="channelcode"></param>
        /// <param name="usercode"></param>
        /// <param name="clientid"></param>
        private static void PushMessageToSingle(string title, string text, string transmissiontype, string transmissioncontent, string woid, string wocode, int wostate, string channelcode, string usercode, string clientid)
        {
            IGtPush push = new IGtPush(_push.HOST, _push.APPKEY, _push.MASTERSECRET);
            //消息模版：TransmissionTemplate:透传模板
            TransmissionTemplate template = TransmissionTemplateDemo(title, text, transmissiontype, transmissioncontent);

            // 单推消息模型
            SingleMessage message = new SingleMessage();
            message.IsOffline = true;                         // 用户当前不在线时，是否离线存储,可选
            message.OfflineExpireTime = 1000 * 3600 * 12;            // 离线有效时间，单位为毫秒，可选
            message.Data = template;
            //判断是否客户端是否wifi环境下推送，2为4G/3G/2G，1为在WIFI环境下，0为不限制环境
            //message.PushNetWorkType = 1;  

            #region 用户clientid
            //获取app客户端clientid   
            com.igetui.api.openservice.igetui.Target target = new com.igetui.api.openservice.igetui.Target();
            target.appId = _push.APPID;
            target.clientId = clientid;
            //target.alias = ALIAS;
            #endregion

            try
            {
                String pushResult = push.pushMessageToSingle(message, target);

                #region 成功推送，记录推送消息
                JObject jsonpush = (JObject)JsonConvert.DeserializeObject(pushResult);
                if (jsonpush["result"].ToString() == "ok")
                {
                    string urlsql = "?woid=" + woid + "&wocode=" + wocode + "&wostate=" + wostate + "&usercode=" + usercode + "&channelcode=" + channelcode;
                    string resultaddmessage = HttpHelper.HttpGet(_push.URL + "messageapi/api/message/addappmessage" + urlsql);
                    Console.WriteLine("\nSuccessfully Pushed - workorder:" + wocode + ",usercode:" + usercode + ",clientid:" + clientid);
                }
                #endregion
                System.Console.WriteLine("The server returns the result:" + pushResult);
            }
            catch (RequestException e)
            {
                String requestId = e.RequestId;
                //发送失败后的重发
                String pushResult = push.pushMessageToSingle(message, target, requestId);
                System.Console.WriteLine("The server returns the result:" + pushResult);
            }
        }
        #endregion

        #region 通知透传模板

        /// <summary>
        /// 通知透传模板动作内容
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        /// <param name="transmissiontype"></param>
        /// <param name="transmissioncontent"></param>
        /// <returns></returns>
        public static NotificationTemplate NotificationTemplateDemo(string title, string text, string transmissiontype, string transmissioncontent)
        {
            NotificationTemplate template = new NotificationTemplate();
            template.AppId = _push.APPID;
            template.AppKey = _push.APPKEY;
            //通知栏标题
            template.Title = title;
            //通知栏内容     
            template.Text = text;
            //通知栏显示本地图片
            template.Logo = _push.AppLogo;
            //通知栏显示网络图标
            template.LogoURL = _push.AppLogoUrl;
            //应用启动类型，1：强制应用启动  2：等待应用启动
            template.TransmissionType = transmissiontype;
            //透传内容  
            template.TransmissionContent = transmissioncontent;
            //接收到消息是否响铃，true：响铃 false：不响铃   
            template.IsRing = true;
            //接收到消息是否震动，true：震动 false：不震动   
            template.IsVibrate = true;
            //接收到消息是否可清除，true：可清除 false：不可清除    
            template.IsClearable = true;
            //设置通知定时展示时间，结束时间与开始时间相差需大于6分钟，消息推送后，客户端将在指定时间差内展示消息（误差6分钟）
            //String begin = "2018-08-01 6:35:01";
            //String end = "2018-08-20 22:59:59";
            //template.setDuration(begin, end);
            return template;
        }        

        /// <summary>
        /// 透传模板动作内容
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        /// <param name="transmissiontype"></param>
        /// <param name="transmissioncontent"></param>
        /// <returns></returns>
        public static TransmissionTemplate TransmissionTemplateDemo(string title, string text, string transmissiontype, string transmissioncontent)
        {
            TransmissionTemplate template = new TransmissionTemplate();
            template.AppId = _push.APPID;
            template.AppKey = _push.APPKEY;
            //应用启动类型，1：强制应用启动 2：等待应用启动
            template.TransmissionType = transmissiontype;
            //透传内容  
            template.TransmissionContent = transmissioncontent;  //透传内容

            //iOS简单推送
            //APNPayload apnpayload = new APNPayload();
            //SimpleAlertMsg alertMsg = new SimpleAlertMsg("alertMsg");
            //apnpayload.AlertMsg = alertMsg;
            //apnpayload.Badge = 11;
            //apnpayload.ContentAvailable = 1;
            //apnpayload.Category = "";
            //apnpayload.Sound = "";
            //apnpayload.addCustomMsg("", "");
            //template.setAPNInfo(apnpayload);

            //APN高级推送
            APNPayload apnpayload = new APNPayload();
            DictionaryAlertMsg alertMsg = new DictionaryAlertMsg();
            alertMsg.Body = transmissioncontent;
            alertMsg.ActionLocKey = "ActionLocKey";
            alertMsg.LocKey = "LocKey";
            alertMsg.addLocArg("LocArg");
            alertMsg.LaunchImage = "LaunchImage";
            //iOS8.2支持字段
            alertMsg.Title = title;
            alertMsg.TitleLocKey = "TitleLocKey";
            alertMsg.addTitleLocArg("TitleLocArg");

            apnpayload.AlertMsg = alertMsg;
            apnpayload.Badge = 10;
            apnpayload.ContentAvailable = 1;
            ////apnpayload.Category = "";
            //apnpayload.Sound = "test1.wav";
            apnpayload.addCustomMsg("payload", "payload");
            //多媒体
            MultiMedia multiMedia = new MultiMedia();
            multiMedia.rid = "xxx-1";
            multiMedia.url = "";
            multiMedia.setIsOnlyWifi(false);
            multiMedia.type = MultiMedia.MediaType.pic;

            List<MultiMedia> list = new List<MultiMedia>();
            list.Add(multiMedia);
            apnpayload.MultiMedias = list;
            template.setAPNInfo(apnpayload);

            //设置通知定时展示时间，结束时间与开始时间相差需大于6分钟，消息推送后，客户端将在指定时间差内展示消息（误差6分钟）
            //String begin = "2018-08-09 6:35:01";
            //String end = "2018-08-30 22:59:59";
            //template.setDuration(begin, end);
            return template;
        }
        #endregion
    }
}
