using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace lkfxdok.LKF.errors
{

    public enum ContextErrorField : int
    {
        kanr = 2, aufnr = 3, aufdat = 40, gebdat = 4, geschl = 6, entdat = 16, satzart = 101, code = 102, ident = 103, massnahme = 104, text = 105,
        text150char = 110, text150byte = 111, feld = 106, feldid = 107, feldname = 108, feldLang = 109, berichtstyp = 120, entabt = 38,
        abtfc = 72, abtfcindex = 74, entabtindex = 75, kst = 81, entkst = 82, kst_entkst = 83, aufid64 = 13,
        alter = 14, alter2 = 12, focuAufnr= 15, childIdent = 18
    }

    [Flags]
    public enum ContextErrorFlags : int
    {
        errorGeneral = 1,
        errorMBDS = 2,
        errorIntScor = 4,
        errorKasKore = 8,
        errorGG = 16,
        errorBericht = 32,
        warningGeneral = 1<<8,
        warningMBDS = 1<<9,
        warningIntScor = 1<<10,
        warningKasKore = 1<<11,
        warningGG = 1<<12,
        warningBericht = 1<<13,
        infoMBDS = 1<<21
    }

    public class ContextErrorList
    {
        ContextErrorFlags _flags;
        protected int[] _errorFields;

        protected ContextErrorList (ContextWithData context, ContextErrorFlags flags, ContextErrorField[] fields)
        {
            _flags = flags;

            if (fields == null || fields.Length == 0)
            {
                _errorFields = null;
                context.CD.SetErrorFormat(6, null);
            }
            else
            {
                _errorFields = new int[fields.Length];
                for (var i = 0; i < fields.Length; i++) _errorFields[i] = (int)fields[i];
                context.CD.SetErrorFormat(0, _errorFields);
            }
        }

        protected ContextErrorList (ContextWithData context, ContextErrorFlags flags, int[] fields)
        {
            _flags = flags;

            if (fields == null || fields.Length == 0)
            {
                _errorFields = null;
                context.CD.SetErrorFormat(6, null);
            }
            else
            {
                _errorFields = new int[fields.Length];
                Array.Copy(fields, _errorFields, fields.Length);
                context.CD.SetErrorFormat(0, _errorFields);
            }
        }

        public static readonly ContextErrorFlags AllErrors = ContextErrorFlags.errorGeneral | ContextErrorFlags.errorMBDS | ContextErrorFlags.errorIntScor | ContextErrorFlags.errorKasKore | ContextErrorFlags.errorBericht | ContextErrorFlags.errorGG;
        public static readonly ContextErrorFlags AllWarnings = ContextErrorFlags.warningGeneral | ContextErrorFlags.warningMBDS | ContextErrorFlags.warningIntScor | ContextErrorFlags.warningKasKore | ContextErrorFlags.warningBericht | ContextErrorFlags.warningGG;
        public static readonly ContextErrorFlags AllInfos = ContextErrorFlags.infoMBDS;
        public static readonly ContextErrorFlags All = AllErrors | AllWarnings | AllInfos;
   
        public static readonly ContextErrorField[] Standard = new ContextErrorField[] { ContextErrorField.kanr, ContextErrorField.aufnr, ContextErrorField.gebdat, ContextErrorField.geschl, ContextErrorField.aufdat,
                                                        ContextErrorField.entdat, ContextErrorField.abtfc, ContextErrorField.satzart, ContextErrorField.feldLang, ContextErrorField.code, ContextErrorField.text150char
    };


}

public class ContextErrorStringList : ContextErrorList
    {

        List<String> _errorLines;

        public ContextErrorStringList(ContextWithData context, ContextErrorFlags flags, ContextErrorField[] fields) : base (context, flags, fields)
        {
            var errorCount = context.CD.SetErrorFilter((uint)flags);
            _errorLines = new List<string>();
            for (uint i = 0; i < errorCount; i++)
            {
                _errorLines.Add(context.CD.GetError(i));
            }
        }

        public ContextErrorStringList(ContextWithData context, ContextErrorFlags flags, int[] fields) : base(context, flags, fields)
        {
            var errorCount = context.CD.SetErrorFilter((uint)flags);
            _errorLines = new List<string>();
            for (uint i = 0; i < errorCount; i++)
            {
                _errorLines.Add(context.CD.GetError(i));
            }
        }

        public int ErrorCount
        {
            get
            {
                return _errorLines.Count;
            }
        }

        public IEnumerable<String> Errors
        {
            get
            {
                return _errorLines;
            }
        }

    }

    public class ContextErrorObjectList : ContextErrorList
    {
        Dictionary<int, int> _positions;
        List<ContextError> _errors;

        public ContextErrorObjectList(ContextWithData context, ContextErrorFlags flags, ContextErrorField[] fields) : base (context, flags, fields)
        {
            Create(context, flags);
        }

        public ContextErrorObjectList(ContextWithData context, ContextErrorFlags flags, int[] fields) : base (context, flags, fields)
        {
            Create(context, flags);
        }

        private void Create(ContextWithData context, ContextErrorFlags flags)
        {
            var errorCount = context.CD.SetErrorFilter((uint)flags);
            _errors = new List<ContextError>();

            if (_errorFields != null)
            {
                int index = 0;
                _positions = new Dictionary<int, int>();
                foreach (var field in _errorFields)
                {
                    _positions[(int)field] = index++;
                }
                for (uint i = 0; i < errorCount; i++)
                {
                    _errors.Add(new ContextError(context, this, i, _errorFields));
                }
            }
            else
            {
                for (uint i = 0; i < errorCount; i++)
                {
                    _errors.Add(new ContextError(context,i));
                }
            }

        }

        public int PositionForErrorField (int errorField)
        {
            int position;
            if (_positions != null && _positions.TryGetValue(errorField, out position))
                return position;
            return -1;
        }

        public int PositionForErrorField (ContextErrorField errorField)
        {
            int position;
            if (_positions != null && _positions.TryGetValue((int)errorField, out position))
                return position;
            return -1;
        }

        public int ErrorCount
        {
            get
            {
                return _errors.Count;
            }
        }

        public IEnumerable<ContextError> Errors
        {
            get
            {
                return _errors;
            }
        }
    }
}
