//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
using System.Dynamic;
using System.IO;

namespace Framefield.Core.ID2a32ff27_5695_42eb_8b1b_558103c54a5f
{
    public class Class_NthMessage : OperatorPart.Function
    {
        //>>> _inputids
        private enum InputId
        {
            FilePath = 0,
            N = 1
        }
        //<<< _inputids
        //>>> _outputids
        private enum OutputId
        {
            Message = 0,
            NumMessages = 1
        }
        //<<< _outputids

        public override void Dispose()
        {
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) 
        {
            //>>> _params
            var FilePath = inputs[(int)InputId.FilePath].Eval(context).Text;
            var N = inputs[(int)InputId.N].Eval(context).Value;
            //<<< _params

            if (FilePath == _lastFile)
                Changed = false;

            _lastFile = FilePath;

            if (Changed)
            {
                Dispose();
                if (File.Exists(FilePath))
                {
                    FileStream stream;
                    try
                    {
                        stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
                        byte[] bytes = new byte[(int)stream.Length];
                        stream.Read(bytes, 0, (int)stream.Length);

                        _messages = new List<String>();
                        int offset = 0;
                        while (offset != -1 && offset < (int)stream.Length)
                        {
                            int startIdx = Find(bytes, _startMessageMarker, offset, (int)bytes.Length - offset);
                            int endIdx = FindFirstNotLetter(bytes, startIdx + _startMessageMarker.Length);
                            offset = endIdx;
                            int length = endIdx - startIdx;
                            if (startIdx >= 0 && length > 10)
                            {
                                byte[] subArray = new byte[length - _startMessageMarker.Length - 2];
                                Array.Copy(bytes, startIdx + _startMessageMarker.Length, subArray, 0, length - _startMessageMarker.Length - 2);
                                _messages.Add(Encoding.ASCII.GetString(subArray));
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Error(this, "error: {0}", e.Message);
                    }

                    Logger.Info(this, "found messages:");
                    foreach (var m in _messages)
                        Logger.Info(this, "{0}", m);
                }
                else
                {
                    Logger.Error(this, "file not found '{0}'", FilePath);
                }
                Changed = false;
            }

            switch ((int)outputIdx)
            {
                case (int)OutputId.Message:
                    if ((int)N >= 0 && (int)N < _messages.Count)
                        context.Text = _messages[(int)N];
                    else
                        context.Text = String.Empty;
                    break;
                case (int)OutputId.NumMessages:
                    context.Value = _messages.Count;
                    break;
            }
            return context;
        }

        public static int Find(byte[] array, byte[] needle, int startIndex, int sourceLength)
        {
            int needleLen = needle.Length;
            int index;

            while (sourceLength >= needleLen)
            {
                index = Array.IndexOf(array, needle[0], startIndex, sourceLength - needleLen + 1);
                if (index == -1)
                    return -1;

                int i, p;
                for (i = 0, p = index; i < needleLen; i++, p++)
                {
                    if (array[p] != needle[i])
                        break;
                }

                if (i == needleLen)
                    return index;

                sourceLength -= (index - startIndex + 1);
                startIndex = index + 1;
            }
            return -1;
        }

        public static int FindFirstNotLetter(byte[] array, int startIndex)
        {
            int i = 0;
            while (startIndex + i < array.Length &&
                   array[startIndex + i] >= 32 && array[startIndex + i] < 123)
            {
                ++i;
            }
            if (startIndex + i >= array.Length)
                return -1;
            return startIndex + i;
        }

        //byte[] _startMessageMarker = new byte[7] {0x47, 0x01, 0x00, 0x4e, 0x02, 0x03, 0x02};
        byte[] _startMessageMarker = new byte[4] {0x47, 0x01, 0x03, 0x02};
        //byte[] _endMessageMarker = new byte[3] {0xf9, 0x86, 0x0c};

        String _lastFile = String.Empty;
        List<String> _messages = new List<String>();
    }
}

