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

using System.Threading;
using System.Threading.Tasks;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

namespace Framefield.Core.ID987cf347_5d85_4b83_b971_041b7337c895
{
    public class Class_TextFragment : OperatorPart.Function
    {
        //>>> _inputids
        private enum InputId
        {
            InputText = 0,
            FragmentStart = 1,
            FragmentCount = 2,
            SplitInto = 3
        }
        //<<< _inputids
        
        //>>> _outputids
        private enum OutputId
        {
            Count = 0,
            Fragment = 1
        }
        //<<< _outputids
        
        private enum EntityTypes {
            Characters = 0,
            Words,
            Lines,            
            Sentences,
        }

        List<List<string>> _tmpList = new List<List<string>>();
        List<String> _resultList = new List<String>();
        String _oldString = "";

        
        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
            //>>> _params
            var InputText = inputs[(int)InputId.InputText].Eval(context).Text;
            var FragmentStart = inputs[(int)InputId.FragmentStart].Eval(context).Value;
            var FragmentCount = inputs[(int)InputId.FragmentCount].Eval(context).Value;
            var SplitInto = (int) inputs[(int)InputId.SplitInto].Eval(context).Value;
            //<<< _params
            
            var needsUpdate = false;
            
            if(InputText != _text || (int)SplitInto != (int) _splitInto) {
                
                _splitInto = (EntityTypes)(int)SplitInto;
                
                switch(_splitInto) {
                    case EntityTypes.Characters:
                        _chunks = new Regex("(.)").Split(InputText); 
                        _delimiter = "";
                        break;
                
                    case EntityTypes.Words:
                        _chunks = new Regex("[\\s\\.\\;\\,()`:]+").Split(InputText); 
                        _delimiter = " ";
                        break;
                        
                    case EntityTypes.Lines:
                        _chunks = new Regex("\\r+\\s*").Split(InputText); 
                        _delimiter = "\n";
                        break;
                        
                    case EntityTypes.Sentences:
                        _chunks = new Regex("\\.[\\s\\.]*").Split(InputText); 
                        _delimiter = ". ";
                        break;

                }
                
                _numberOfChunks =  _chunks.Length > 0 && String.IsNullOrEmpty(_chunks[ _chunks.Length -1]) 
                                ? _chunks.Length -1
                                : _chunks.Length;
                
                
                _lastFragment = "";
                needsUpdate= true;
            }
            
            if(needsUpdate ||  (int)FragmentStart != _fragmentStart || (int)FragmentCount != _fragmentCount) {
                _fragmentStart = (int)FragmentStart;
                _fragmentCount = (_splitInto == EntityTypes.Characters) 
                                ? (int)FragmentCount *2
                                : (int)FragmentCount ;
                _lastFragment = GetFragment(_fragmentStart, _fragmentCount);            
                context.Text = _lastFragment;
            }
            
            switch((int)outputIdx) {
                case (int)OutputId.Fragment:
                    context.Text = _lastFragment;
                    Logger.Info("Text: " + _lastFragment);
                    
                    break;

                case (int)OutputId.Count:
                    context.Value= _chunks.Length;
                    break;
                    
                default:
                    break;
            }
            
            return context;
        }
        
        private string GetFragment(int startFragment, int fragmentCount)
        {
            var d = "";
            if(fragmentCount <= 0)
                return "";

            var sb = new StringBuilder();
            for(var index = 0; index < fragmentCount; index++) 
            {
                var moduloIndex = (startFragment + index) % _numberOfChunks;
                if(moduloIndex < 0)
                    moduloIndex += _numberOfChunks;
                    
                sb.Append(d);
                sb.Append(_chunks[moduloIndex]);
                d = _delimiter;
                
            }
            return sb.ToString();
            

        }

        private int _fragmentStart = 0;
        private int _fragmentCount = 0;
        private string _lastFragment;
        private string _delimiter;
        private string[] _chunks;
        private int _numberOfChunks = 1;    // without empty tail
        
        private EntityTypes  _splitInto; 
        private String _text;
    }    
}

