using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;
using VIZ.Framework.Domain;

namespace VIZ.Framework.Connection
{
    /// <summary>
    /// 包处理器 -- 命令行
    /// </summary>
    [ConnPackageProvider(ConnPackageProviderType.TCP | ConnPackageProviderType.UDP)]
    public class ConnCommandLinePackageProvider : IConnPackageProvider
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(ConnCommandLinePackageProvider));

        /// <summary>
        /// 数据编码
        /// </summary>
        public Encoding Encoding { get; set; } = Encoding.UTF8;

        /// <summary>
        /// 最后的命令字符串,用于处理连包数据
        /// </summary>
        private string lastCommandString;

        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="package">数据包</param>
        public void Execute(ConnPackageInfo package)
        {
            string str = this.Encoding.GetString(package.Data, 0, package.DataSize);
            if (string.IsNullOrWhiteSpace(str))
                return;

            str = this.lastCommandString + str;
            this.lastCommandString = null;

            string[] commands = str.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            // 最后一个命令是否完整
            bool isLastCommandComplete = str.EndsWith("\n") || str.EndsWith("\r");

            for (int i = 0; i < commands.Length; i++)
            {
                if (i == commands.Length - 1 && !isLastCommandComplete)
                {
                    this.lastCommandString = commands[i];
                    break;
                }

                // 处理器处理消息
                ConnCommandLineInfo info = new ConnCommandLineInfo();
                info.RemoteIP = package.RemoteIP;
                info.RemotePort = package.RemotePort;
                info.LocalIP = package.LocalIP;
                info.LocalPort = package.LocalPort;
                info.Command = commands[i];

                try
                {
                    this.Execute(info);
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }

                // 发送消息
                ConnCommandLineMessage msg = new ConnCommandLineMessage();
                msg.RemoteIP = package.RemoteIP;
                msg.RemotePort = package.RemotePort;
                msg.LocalIP = package.LocalIP;
                msg.LocalPort = package.LocalPort;
                msg.PortName = package.PortName;
                msg.Provider = this;
                msg.Command = commands[i];

                try
                {
                    ApplicationDomain.MessageManager.Send(msg);
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }
        }

        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="info">信息</param>
        protected virtual void Execute(ConnCommandLineInfo info)
        {
            // nothing to do.
        }
    }
}
