
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Controls;

namespace AIRS
{
    /// <summary>
    /// Python脚本执行类
    /// lbf 2020/05/20 14:43
    /// </summary>
    public  class PythonExecutor :ScriptExecutor
    {

        /// <summary>
        /// IBM组织识别、标准评级py脚本文件
        /// </summary>
        public string IbmAiPy { get; set; }



        private readonly string ReturnDataPrefix = "AI_result";//"{\"content\":";
        private readonly string ParameterErrorPrefix = "AI_error:";
        private readonly string ProgressPrefix = "AI_progress:";
        private readonly int ARGUMENTS_MAX_LENGTH = 1024 * 32;//命令行参数最大长度

        /// <summary>
        /// python执行器，返回数据更新界面控件
        /// </summary>
        /// <param name="context">界面UI环境</param>
        public PythonExecutor(SynchronizationContext context):base(context,"python")
        {
            this.IbmAiPy = @"D:\vi\vi_server\ibm_ai.py ";
        }
        /// <summary>
        /// python执行器，返回数据更新界面控件
        /// </summary>
        /// <param name="context">界面UI环境</param>
        /// <param name="pyFilePath">要执行的python脚本文件全路径</param>
        public PythonExecutor(SynchronizationContext context,string pyFilePath) : base(context, "python")
        {
            this.IbmAiPy = pyFilePath;
        }
        /// <summary>
        /// 停止后台脚本运行
        /// </summary>
        public void stop()
        {
            lock(this.IbmAiPy)
            {
                string stop_file = Path.Combine(Path.GetDirectoryName(this.IbmAiPy), "stop.ai");
                if (!File.Exists(stop_file))
                {
                    File.Create(stop_file);
                }
            }

        }

        /// <summary>
        /// 执行python文件脚本
        /// </summary>
        /// <param name="control">回调界面控件</param>
        /// <param name="pyPath">要执行的python脚本文件全路径</param>
        /// <param name="parameters">参数</param>
        public void executePy(Control control, params string[] parameters)
        {
            StringBuilder stringBuilder = new StringBuilder(256);
            stringBuilder.Append(this.IbmAiPy);
            if (parameters != null)
            {
                foreach (var parameter in parameters)
                {
                    stringBuilder.Append(" \"");
                    stringBuilder.Append(parameter.Replace("'", "\\\"").Replace("\"", "\\\""));
                    stringBuilder.Append("\" ");
                }
            }
            execute(control, stringBuilder.ToString());
        }
        /// <summary>
        /// 标准评级python接口调用，需要挂载ReceivedControlData接收返回值 
        /// </summary>
        /// <param name="control">回调显示控件</param>
        /// <param name="catagory">评级钢种ID</param>
        /// <param name="items">检测项目ID</param>
        /// <param name="parameters">其他参数</param>
        /// <param name="jpgFileList">等检测项目图像文件全名列表</param>
        public void ibmBzpj(Control control,string catagory,string items,object detectParams, List<string> jpgFileList)
        {
            Assert.IsNotNull(jpgFileList);
            Assert.IsNotEmpty(jpgFileList);
            Hashtable json = new Hashtable();
            json.Add("func", "bzpj");
            json.Add("catagory", catagory);
            json.Add("items", items);
            json.Add("path", Path.GetDirectoryName(jpgFileList[0]).Replace("\\", "/"));
            json.Add("images", string.Join(";", jpgFileList.Select(s => Path.GetFileName(s))));
            string arguments = JsonConvert.SerializeObject(json).Replace("\"", "\\\"");
            Assert.Less(Encoding.UTF8.GetBytes(arguments).Length, this.ARGUMENTS_MAX_LENGTH);
            string commandString;
            string vp = null;
            if (detectParams != null)
            {
                
                if (detectParams.GetType() == typeof(string))
                {
                    vp = detectParams.ToString().Replace("'", "\\\"");
                }
                else
                {
                    vp = JsonConvert.SerializeObject(detectParams).Replace("\"", "\\\"");
                }
                
            }
            
            if (!string.IsNullOrEmpty(vp))
            {
                commandString = string.Format("{0} \"{1}\" \"{2}\"", this.IbmAiPy, arguments, vp);
            }
            else
            {
                commandString = string.Format("{0} \"{1}\"", this.IbmAiPy, arguments);
            }
            System.Diagnostics.Debug.WriteLine(commandString);
            execute(control, commandString);
        }
        /// <summary>
        /// IBM组织识别python接口调用,需要挂载ReceivedControlData接收返回值 
        /// </summary>
        /// <param name="control">回调显示控件</param>
        /// <param name="detectParams">其他参数</param>
        /// <param name="jpgFileList">等检测项目图像文件全名列表</param>
        public void ibmZzsb(Control control, object detectParams, List<string> jpgFileList)
        {
            Assert.IsNotNull(jpgFileList);
            Assert.IsNotEmpty(jpgFileList);
            Hashtable json = new Hashtable();
            json.Add("catagory", "-1");
            json.Add("status", "-1");
            json.Add("magnification", "-1");
            json.Add("func", "zzsb");
            json.Add("path", Path.GetDirectoryName(jpgFileList[0]).Replace("\\", "/"));
            json.Add("images", string.Join(";", jpgFileList.Select(s => Path.GetFileName(s))));

            string arguments = JsonConvert.SerializeObject(json).Replace("\"", "\\\"");
            Assert.Less(Encoding.UTF8.GetBytes(arguments).Length,this.ARGUMENTS_MAX_LENGTH);
            string commandString;
            if (detectParams != null && !string.IsNullOrEmpty(detectParams.ToString()))
            {
                commandString = string.Format("{0} \"{1}\" \"{2}\"", this.IbmAiPy, arguments,detectParams.ToString().Replace("'", "\\\""));
            }
            else
            {
                commandString = string.Format("{0} \"{1}\"", this.IbmAiPy, arguments);
            }

           
            execute(control, commandString);
        }
        /// <summary>
        /// 返回数据开头信息确认是什么类型数据，分为返回结果、一般信息、参数错误信息、执行的脚本命令
        /// </summary>
        /// <param name="control"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        override
        protected ControlData produceControlData(Control control, DataReceivedEventArgs e)
        {
            ControlData controlData = new ControlData { Control = control };
            //不同类型返回数据
            if (e.Data.Contains(this.ReturnDataPrefix))
            {
                controlData.DataString = e.Data.Substring(e.Data.IndexOf(this.ReturnDataPrefix));
                controlData.CallbackDataType= CallbackDataType.ReturnData;
                int contentPos = controlData.DataString.IndexOf(',');
                int indexPos = controlData.DataString.IndexOf(':');
                if (contentPos >= 0)
                {
                    controlData.Index = int.Parse(controlData.DataString.Substring(indexPos + 1, contentPos - indexPos - 1));
                    controlData.DataString = controlData.DataString.Substring(contentPos + 1);
                }
                else
                {
                    controlData.DataString = controlData.DataString.Substring(indexPos + 1);
                }
                
            }
            else if (e.Data.Contains(this.ParameterErrorPrefix))
            {
                controlData.DataString = e.Data.Substring(e.Data.IndexOf(this.ParameterErrorPrefix));
                controlData.CallbackDataType = CallbackDataType.ParameterError;
            }
            else if (e.Data.Contains(this.ProgressPrefix))
            {
                controlData.DataString = e.Data.Substring(e.Data.IndexOf(this.ProgressPrefix));
                controlData.CallbackDataType = CallbackDataType.Progress;
            }
            else
            {
                controlData.DataString = e.Data;
                controlData.CallbackDataType = CallbackDataType.Info;
            }
            return controlData;
        }

    }
   
}