using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Ropin.Inspection.Common.Helper
{
    public class LiveGBSHelper
    {
        public static string loginUrl= "http://124.71.132.255:10000/";
        private const string username = "admin";
        private const string password = "62582E39C499493DCBB1344A9BCB897B";
        private static GBSToken tokenResult;
        //登录-获取token
        public static async Task<GBSToken> GetToken()
        {
            if (tokenResult != null && DateTime.Now < tokenResult.tokenDate)
            {
                return tokenResult;
            }
            var url = $"{loginUrl}api/v1/login?username={username}&password={password}";
            GBSToken token=null;
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        token = JsonConvert.DeserializeObject<GBSToken>(result);
                        tokenResult=token;
                        tokenResult.tokenDate = DateTime.Now.AddMilliseconds(tokenResult.TokenTimeout);
                    }
                }
                return token;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        //设备信息 - 查询设备通道列表
        public static async Task<DeviceChanneModel> GetDeviceChannellist()
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            DeviceChanneModel model = new DeviceChanneModel();
            var url = $"{loginUrl}api/v1/device/channellist?token={tokenResult.URLToken}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<DeviceChanneModel>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 实时直播 - 开始直播
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <returns></returns>
        public static async Task<ChannelVideo> GeChannelVideo(string serial,string channelId)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            ChannelVideo model = new ChannelVideo();
            var url = $"{loginUrl}api/v1/stream/start?token={tokenResult.URLToken}&serial={serial}&code={channelId}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<ChannelVideo>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 实时录像 - 实时录像开始
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <returns></returns>
        public static async Task<VideoStartRecording> StartRecording(string serial, string channelId)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            VideoStartRecording DownloadURL = null;
            var url = $"{loginUrl}api/v1/record/start?token={tokenResult.URLToken}&serial={serial}&code={channelId}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        DownloadURL = JsonConvert.DeserializeObject<VideoStartRecording>(result);

                    }
                }
                return DownloadURL;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 实时录像 - 实时录像停止
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <returns></returns>
        public static async Task<VideoRecording> StopRecording(string serial, string channelId)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            VideoRecording model = null;
            var url = $"{loginUrl}api/v1/record/stop?token={tokenResult.URLToken}&serial={serial}&code={channelId}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<VideoRecording>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 云端服务器录像 - 按日查询通道录像
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <param name="date">日期, YYYYMMDD</param>
        /// <returns></returns>
        public static async Task<cloudrecordQuerydaily> cloudrecordQuerydaily(string serial, string channelId,string date)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            cloudrecordQuerydaily model = null;
            var url = $"{loginUrl}api/v1/cloudrecord/querydaily?token={tokenResult.URLToken}&serial={serial}&code={channelId}&period={date}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<cloudrecordQuerydaily>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #region 前端设备录像
        /// <summary>
        /// 前端设备录像 - 查询录像列表
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <param name="starDate">开始时间, YYYY-MM-DDTHH:mm:ss</param>
        /// <param name="endDate">结束时间, YYYY-MM-DDTHH:mm:ss</param>
        /// <returns></returns>
        public static async Task<playbackRecordList> playbackRecordList(string serial, string channelId, string starDate,string endDate)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            playbackRecordList model = null;
            var url = $"{loginUrl}api/v1/playback/recordlist?token={tokenResult.URLToken}&serial={serial}&code={channelId}&starttime={starDate}&endtime={endDate}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<playbackRecordList>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 前端设备录像 - 开始回放
        /// </summary>
        /// <param name="serial">设备编号</param>
        /// <param name="channelId">通道编号</param>
        /// <param name="starDate">开始时间, YYYY-MM-DDTHH:mm:ss</param>
        /// <param name="endDate">结束时间, YYYY-MM-DDTHH:mm:ss</param>
        /// <returns></returns>
        public static async Task<ChannelVideo> playbackStart(string serial, string channelId, string starDate, string endDate,bool Download=false,int DownloadSpeed=4)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            ChannelVideo model = new ChannelVideo();
            var url = $"{loginUrl}api/v1/playback/start?token={tokenResult.URLToken}&serial={serial}&code={channelId}&starttime={starDate}&endtime={endDate}";
            if (Download)
            {
                url = $"{loginUrl}api/v1/playback/start?token={tokenResult.URLToken}&serial={serial}&code={channelId}&starttime={starDate}&endtime={endDate}&download={Download}&download_speed={DownloadSpeed}";
            }
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<ChannelVideo>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 前端设备录像 - 回放控制
        /// </summary>
        /// <param name="streamid">回放流ID, 由开始回放接口(PlaybackStart)返回</param>
        /// <param name="command">回放控制类型 允许值: play, pause, teardown, scale</param>
        /// <param name="range">command=play 时有效,表示从当前位置以当前播放速度跳转到指定range(单位s)的时间点播放;range=now 表示从当前位置开始播放,比如:暂停后恢复播放,则指定range=now  默认值: now</param>
        /// <param name="scale">command=scale 时有效,倍数播放倍率,1=正常播放,大于0小于1为慢放,如:0.5=以0.5倍的速度慢放;大于1为快放,如:2=以2倍的速度快放,负数为倒放,参数意义相同  默认值: 2</param>
        /// <returns></returns>
        public static async Task<string> playbackControl(string streamid,string command,string range="now",int scale=2)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            string bol = "false";
            var url = $"{loginUrl}api/v1/playback/control?token={tokenResult.URLToken}&streamid={streamid}&command={command}";
            if (command== "play")
            {
                url = $"{loginUrl}api/v1/playback/control?token={tokenResult.URLToken}&streamid={streamid}&command={command}&range={range}";
            }else if (command== "scale")
            {
                url = $"{loginUrl}api/v1/playback/control?token={tokenResult.URLToken}&streamid={streamid}&command={command}&scale={scale}";
            }
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        bol=JsonConvert.DeserializeObject<string>(result);
                    }
                }
                return bol;
            }
            catch (Exception ex)
            {
                return "error";
            }
        }

        /// <summary>
        /// 前端设备录像 - 回放流停止
        /// </summary>
        /// <param name="streamid">回放流ID, 由开始回放接口(PlaybackStart)返回</param>
        /// <returns></returns>
        public static async Task<playbackStopPlaybackFileURL> playbackStop(string streamid)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            playbackStopPlaybackFileURL model = new playbackStopPlaybackFileURL();
            var url = $"{loginUrl}api/v1/playback/stop?token={tokenResult.URLToken}&streamid={streamid}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<playbackStopPlaybackFileURL>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 前端设备录像 - 单条回放流信息
        /// </summary>
        /// <param name="streamid">回放流ID, 由开始回放接口(PlaybackStart)返回</param>
        /// <returns></returns>
        public static async Task<playbackStreaminfoEntity> playbackStreaminfo(string streamid)
        {
            if (tokenResult == null || DateTime.Now >= tokenResult.tokenDate)
            {
                tokenResult = await GetToken();
            }
            playbackStreaminfoEntity model = new playbackStreaminfoEntity();
            var url = $"{loginUrl}api/v1/playback/streaminfo?token={tokenResult.URLToken}&streamid={streamid}";
            try
            {
                using (HttpClient http = new HttpClient())
                {
                    var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                    requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await http.SendAsync(requestt);
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        string result = await response.Content.ReadAsStringAsync();
                        model = JsonConvert.DeserializeObject<playbackStreaminfoEntity>(result);
                    }
                }
                return model;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #endregion
    }
}
public class GBSToken
{
    public string CookieToken { get; set; }
    public string URLToken { get; set; }
    public string StreamToken { get; set; }
    public int TokenTimeout { get; set; }
    public DateTime tokenDate { get; set; }
}
public class DeviceChanneModel
{
    public int ChannelCount { get; set; }
    public List<ChanneModel> ChannelList { get; set; }
}
public class ChanneModel
{
    public string ID { get; set; } //通道编号
    public string DeviceID { get; set; }//设备编号
    public string DeviceName { get; set; }//设备名称
    public string DeviceCustomName { get; set; }//设备自定义名称
    public bool DeviceOnline { get; set; }//设备在线状态
    public int Channel { get; set; }//通道序号
    public string Name { get; set; }//通道名称
    public string CustomName { get; set; }//通道自定义名称
    public string SnapURL { get; set; }//通道快照链接
    public string Manufacturer { get; set; }//通道设备厂家
    public string CustomManufacturer { get; set; }//通道自定义设备厂家
    public string Model { get; set; }//通道设备型号
    public string CustomModel { get; set; }//通道自定义设备型号
    public string Owner { get; set; }//通道设备归属
    public string CivilCode { get; set; }//行政区域
    public string CustomCivilCode { get; set; }//自定义行政区域
    public string Address { get; set; }//安装地址
    public string CustomAddress { get; set; }//自定义安装地址
    public string Firmware { get; set; }//固件版本
    public string CustomFirmware { get; set; }//自定义固件版本
    public string SerialNumber { get; set; }    //设备序列号
    public string CustomSerialNumber { get; set; }  //自定义设备序列号
    public string IPAddress{get;set; }//设备/区域/系统IP地址
    public string CustomIPAddress { get; set; }//自定义设备/区域/系统IP地址
    public int Port { get; set; }//设备/区域/系统端口
    public int CustomPort { get; set; }//自定义设备/区域/系统端口
    public int Parental { get; set; }//当为通道设备时, 是否有通道子设备, 1-有,0-没有
    public string ParentID { get; set; }//直接上级编号
    public string CustomParentID { get; set; }//自定义直接上级编号
    public int Secrecy { get; set; }//保密属性, 缺省为0, 0-不涉密, 1-涉密
    public int RegisterWay { get; set; }//注册方式, 缺省为1, 1-IETF RFC3261, 2-基于口令的双向认证, 3-基于数字证书的双向认证
    public string Status { get; set; }//在线状态 允许值: ON, OFF
}

public class ChannelVideo
{
    public string StreamID { get; set; }//回放流ID
    public string SMSID { get; set; }//流媒体编号
    public string DeviceID { get; set; }//设备编号
    public string ChannelID { get; set; }//通道编号
    public string ChannelName { get; set; }//通道名称
    public string FLV { get; set; }//HTTP-FLV 播放地址
    public string HLS { get; set; }//HLS(M3U8) 播放地址
    public string RTSP { get; set; }//RTSP 播放地址, 需要 SMS 配置 RTSP 端口开启 RTSP 服务
    public string RTMP { get; set; }//RTMP 播放地址
    public string SnapURL { get; set; }//快照地址
    public string WEBRTC { get; set; }//WEBRTC 播放地址
    public string WS_FLV { get; set; }//Websocket-FLV 播放地址

}

public class VideoRecording
{
    public string StreamID { get; set; }
    public int RecordCount { get; set; }
    public List<VideoRecordingMode> RecordList { get; set; }
}
public class VideoRecordingMode
{
   public string StartTime { get; set; }// 录像文件起始时间, YYYYMMDDHHmmss
    public string EndTime { get; set; }//录像文件结束时间, YYYYMMDDHHmmss
    public string DownloadURL  { get; set; }//录像文件下载地址, EndTime 不为空时方可用
}
public class VideoStartRecording
{
    public string DownloadURL { get; set; }
}
public class playbackStopPlaybackFileURL
{
    public string PlaybackFileURL { get; set; }
}
public class cloudrecordQuerydaily
{
    //通道名称
    public string name { get; set; }
    //通道水印
    public string osd { get; set; }
    public List<recordQuerydaily> list { get; set; }
}
public class recordQuerydaily
{
    //通道名称
    public string name {get;set;}
    //开始时间, YYYYMMDDHHmmss
    public string startAt  {get;set;}
    //录像时长(秒)
    public double duration { get; set; }
    //录像播放链接
    public string hls { get; set; }
    //重要标记
    public bool important { get; set; }
}
public class playbackRecordList
{
    //通道编号
    public string DeviceID { get; set; }
    //通道名称
    public string Name { get; set; }
    //录像总数
    public int SumNum { get; set; }
    //录像列表
    public List<RecordList> RecordList { get; set; }
}
public class RecordList
{
    //摄像头名称
    public string CameraName { get; set; }
    //通道编号
    public string ChannelID { get; set; }
    //设备编号
    public string DeviceID { get; set; }
    //通道名称
    public string Name { get; set; }
    //文件路径名
    public string FilePath { get; set; }
    //录像地址
    public string Address { get; set; }
    //录像开始时间, YYYY-MM-DDTHH:mm:ss
    public string StartTime { get; set; }
    //录像结束时间, YYYY-MM-DDTHH:mm:ss
    public string EndTime { get; set; }
    //保密属性, 0-不涉密, 1-涉密 允许值: 0, 1
    public string Secrecy { get; set; }
    //录像产生类型 允许值: time, alarm, manual, all
    public string Type { get; set; }
    //录像触发者ID
    public string RecorderID { get; set; }
}

public class playbackStreaminfoEntity
{
    public string StreamID { get; set; }//回放流ID
    public string SMSID { get; set; }//流媒体编号
    public string DeviceID { get; set; }//设备编号
    public string ChannelID { get; set; }//通道编号
    public string ChannelName { get; set; }//通道名称
    public string WEBRTC { get; set; }//WEBRTC 播放地址
    public string FLV { get; set; }//HTTP-FLV 播放地址
    public string WS_FLV { get; set; }//Websocket-FLV 播放地址
    public string RTMP { get; set; }//RTMP 播放地址
    public string HLS { get; set; }//HLS(M3U8) 播放地址
    public string StartAt { get; set; }//开始时间
    public string RecordStartAt { get; set; }//实时录像开始时间
    public int Duration { get; set; }//持续时间(秒)
    public string SourceVideoCodecName { get; set; }//原始视频编码
    public int SourceVideoWidth { get; set; }//原始视频宽
    public int SourceVideoHeight { get; set; }//原始视频高
    public double SourceVideoFrameRate { get; set; }//原始视频帧率
    public string SourceAudioCodecName { get; set; }//原始音频编码
    public double SourceAudioSampleRate { get; set; }//原始音频采样率
    public int RTPCount { get; set; }//收包数
    public int RTPLostCount { get; set; }//丢包数
    public double RTPLostRate { get; set; }//丢包率百分比
    public int VideoFrameCount { get; set; }//视频帧数
    public int InBytes { get; set; }//收流字节大小(Byte)
    public double InBitRate { get; set; }//收流平均码率(Kbps)
    public int OutBytes { get; set; }//分发流字节大小(Byte)
    public int PlaybackDuration { get; set; }//回放文件总时长(秒)
    public int TimestampSec { get; set; }//当前回放时长(秒)
    public double PlaybackProgress { get; set; }//回放进度([0-1]), 按时间截计算(TimestampSec/PlaybackDuration)
    public double DownloadProgress { get; set; }//下载进度([0-1]), 按文件大小计算(InBytes/PlaybackFileSize)
    public double PlaybackFileSizea { get; set; }//下载文件总大小
    public string PlaybackFileURL { get; set; }//下载文件链接, playback stop 之后方可用
    public string PlaybackFileError { get; set; }//下载文件异常终止消息
}