using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using DevExpress.XtraEditors;
namespace Ips.Sps.IfeSpects
{
    public partial class IfeSpectCtrl : XtraUserControl
    {
        IntPtr speView = IntPtr.Zero;
        public IfeSpectCtrl()
        {
            InitializeComponent();
        }
        static IfeSpectCtrl()
        {
            IfeQTSpect.Init();
        }
        /// 
        /// 重写 DesignMode
        /// 
        protected new bool DesignMode
        {
            get
            {
                bool flag = false;
                if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
                {
                    flag = true;
                }
                else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToUpper().Equals("DEVENV"))
                {
                    flag = true;
                }
                return flag;
            }
        }
        /// 
        /// 频谱窗口大小发生改变
        /// 
        /// 
        /// 
        private void spePanel_Resize(object sender, EventArgs e)
        {
            if (DesignMode)
                return;
            if (speView != IntPtr.Zero)
            {
                IfeQTSpect.ResizeView(speView, this.spePanel.Width, this.spePanel.Height);
            }
        }
        /// 
        /// 
        /// 
        /// 
        public void RegisterSelectIndexChanged(IfeQTSpect.SelectIndexChanged fun)
        {
            if (speView != IntPtr.Zero)
            {
                IfeQTSpect.RegisterSelectIndexChanged(speView, fun);
            }
        }
        /// 
        /// 清空信号展示页面
        /// 
        public void Clear()
        {
            if (speView != IntPtr.Zero)
            {
                IfeQTSpect.Clear(speView);
            }
        }
        /// 
        /// 选中指定频率
        /// 
        /// 
        public void HitFrequence(double freq)
        {
            if (speView != IntPtr.Zero)
            {
                IfeQTSpect.SelectFrequence(speView, freq);
            }
        }
        /// 
        /// 空间初始化
        /// 
        /// 
        /// 
        private void ItcSpectrum_Load(object sender, EventArgs e)
        {
            if (DesignMode)
                return;
            //频谱绘制
            speView = IfeQTSpect.CreateView(this.spePanel.Handle, this.spePanel.Width, this.spePanel.Height);
            //test
            //SetSource(@"E:\1.dat", 100000000, false, 1031000000, 13, 40, false, 100, 1500000, 5);
        }
        private double[] SetRealSource(String fileName, int fsample, UInt64 midFreq, int fftOrder, int smoothCount
         , bool autodoor, double doorline, int detectBw, double detectSnr)
        {
            double[] ret = null;
            if (speView != IntPtr.Zero)
            {
                IntPtr fft = IfeQTSpect.CalcFFT(fileName, false, fftOrder, smoothCount);
                int len = (int)Math.Pow(2, fftOrder - 1);
                float[] ckfft = new float[len];
                Marshal.Copy(fft, ckfft, 0, len);
                int sigCount = 1000;
                double[] tmp = new double[sigCount * 3];
                float fFreqReso = (float)(fsample / 2.0 / len);
                //IfeQTSpect.SignalDetecting(ckfft, len, fFreqReso, 1.0f, tmp, ref sigCount);
                IfeQTSpect.SignalDetecting(ckfft, len, fFreqReso, detectSnr, tmp, ref sigCount);
                double[] sigs = null;
                if (sigCount > 0)
                {
                    ret = new double[sigCount * 3];
                    sigs = new double[sigCount * 3];
                    for (int idx = 0; idx < sigCount; ++idx)
                    {
                        sigs[3 * idx] = tmp[3 * idx];
                        sigs[3 * idx + 1] = tmp[3 * idx + 1];
                        sigs[3 * idx + 2] = tmp[3 * idx + 2];
                        ret[3 * idx] = tmp[3 * idx] + midFreq - 20000000;
                        ret[3 * idx + 1] = tmp[3 * idx + 1];
                        ret[3 * idx + 2] = tmp[3 * idx + 2];
                    }
                }
                IfeQTSpect.ShowFFT(speView, fft, len, false, fsample, midFreq - 20000000, sigs, sigCount);
                IfeQTSpect.freeBuffer(fft);
            }
            return ret;
        }
        private double[] SetIQSource(String fileName, int fsample, UInt64 midFreq, int fftOrder, int smoothCount
           , bool autodoor, double doorline, int detectBw, double detectSnr)
        {
            double[] ret = null;
            if (speView != IntPtr.Zero)
            {
                IntPtr fft = IfeQTSpect.CalcFFT(fileName, true, fftOrder, smoothCount);
                int len = (int)Math.Pow(2, fftOrder);
                IntPtr tmpFFT = IntPtr.Add(fft, (int)(len * 0.1) * sizeof(float));
                float[] ckfft = new float[(int)(len * 0.8)];
                Marshal.Copy(tmpFFT, ckfft, 0, (int)(len * 0.8));
                int sigCount = 1000;
                double[] tmp = new double[sigCount * 3];
                float fFreqReso = (float)(fsample * 1.0 / len);
                //IfeQTSpect.SignalDetecting(ckfft, (int)(len * 0.8), fFreqReso, 1.0f, tmp, ref sigCount);
                IfeQTSpect.SignalDetecting(ckfft, (int)(len * 0.8), fFreqReso, detectSnr, tmp, ref sigCount);
                double[] sigs = null;
                if (sigCount > 0)
                {
                    ret = new double[sigCount * 3];
                    sigs = new double[sigCount * 3];
                    for (int idx = 0; idx < sigCount; ++idx)
                    {
                        sigs[3 * idx] = tmp[3 * idx] + fsample * 0.1 /*+ (midFreq - (UInt64)fsample / 2)*/;
                        sigs[3 * idx + 1] = tmp[3 * idx + 1];
                        sigs[3 * idx + 2] = tmp[3 * idx + 2];
                        ret[3 * idx] = tmp[3 * idx] + fsample * 0.1 + (midFreq - (UInt64)fsample / 2);
                        ret[3 * idx + 1] = tmp[3 * idx + 1];
                        ret[3 * idx + 2] = tmp[3 * idx + 2];
                    }
                }
                IfeQTSpect.ShowFFT(speView, fft, len, true, fsample, (midFreq - (UInt64)fsample / 2), sigs, sigCount);
                IfeQTSpect.freeBuffer(fft);
            }
            return ret;
        }
        /// 
        /// 设置数据源
        /// 
        /// 原始文件
        /// 采样率 Hz
        /// 是否IQ数据
        /// 显示的最小频率
        /// fft阶数
        /// 平滑次数
        /// 
        /// 
        /// 
        /// 
        public double[] SetSource(String fileName, int fsample, bool beIQ, UInt64 midFreq, int fftOrder, int smoothCount
             , bool autodoor, double doorline, int detectBw, double detectSnr)
        {
            double[] ret = null;
            if (!beIQ)
            {
                ret = SetRealSource(fileName, fsample, midFreq, fftOrder, smoothCount, autodoor, doorline, detectBw, detectSnr);
            }
            else
            {
                ret = SetIQSource(fileName, fsample, midFreq, fftOrder, smoothCount, autodoor, doorline, detectBw, detectSnr);
            }
            return ret;
        }
    }
    public class IfeQTSpect
    {
        //动态库位置
        public const string dllName = @"IfeSpect\IfeSpect.dll";
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern bool SignalDetecting(float[] Spectrum, int SpecLen, double freqReso, double snrThreshold, double[] Sig, ref int SigNum);
        /// 
        /// 界面当前选择改变
        /// 
        /// 
        public delegate void SelectIndexChanged(int index);
        /// 
        /// 初始化 必须在Main函数中提前调用
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void Init();
        /// 
        /// 创建一个频谱展示控件
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr CreateView(IntPtr parent, int w, int h);
        /// 
        /// 销毁控件
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void DestoryView(IntPtr view);
        /// 
        /// 计算频谱
        /// 
        /// 
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr CalcFFT(String fileName, bool beIQ, int fftOrder, int smoothCount);
        /// 
        /// 释放C++申请的内存空间
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void freeBuffer(IntPtr ptr);
        /// 
        /// 显示频谱数据
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ShowFFT(IntPtr ptr, IntPtr buffer, int len, bool beIQ
           , int fsample, UInt64 minFreq
           , double[] sig, int siglen);
        /// 
        /// 输入频谱检测信号
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr fftCheck(IntPtr fftbuffer, int len, ref int reslen
            , double sf, double ef, double bw
            , bool autodoor, double doorline, int detectBw, double detectSnr);
        /// 
        /// 注册界面信号变动
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void RegisterSelectIndexChanged(IntPtr ptr, SelectIndexChanged fun);
        /// 
        /// 创建一个频谱展示控件
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ResizeView(IntPtr ptr, int w, int h);
        /// 
        /// 清空页面展示
        /// 
        /// 
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void Clear(IntPtr ptr);
        /// 
        /// 设置显示范围
        /// 
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetShowRangeX(IntPtr ptr, double vMin, double vMax);
        /// 
        /// 选中一个信号 
        /// 
        /// 信号中心频率
        [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SelectFrequence(IntPtr ptr, double freq);
    }
}