using System;
using System.Linq.Expressions;

namespace InABox.Core
{
    // EntityForm no longer is an IOneToMany, so any subclasses must add this if they want to.

    public interface IEntityForm
    {
        string Description { get; set; }
    }

    [Caption("Digital Forms")]
    public abstract class EntityForm<TParent, TParentLink, TThis> : Entity, IRemotable, IPersistent, ISequenceable, IStringAutoIncrement<TThis>,
        IEntityForm,
        IDigitalFormInstance<TParentLink>, ILicense<DigitalFormsLicense>
        where TThis : EntityForm<TParent,TParentLink, TThis>
        where TParent : Entity
        where TParentLink : BaseObject, IEntityLink<TParent>, new()
    {

        public Expression<Func<TThis, string>> AutoIncrementField() => x => x.Number;

        public abstract string AutoIncrementPrefix();

        public virtual string AutoIncrementFormat() => "{0:D6}";
        
        public Filter<TThis>? AutoIncrementFilter() => null;
        
        [EditorSequence(1)]
        [CodeEditor(Editable = Editable.Disabled)]
        public String Number { get; set; }

        [EditorSequence(2)]
        public string Description { get; set; } = "";

        [NullEditor]
        [EntityRelationship(DeleteAction.Cascade)]
        public virtual TParentLink Parent => InitializeField(ref _tParentLink, nameof(TParentLink));
        private TParentLink _tParentLink;

        [NullEditor]
        [Obsolete("Being Replaced by Form")]
        public QAFormLink QAForm => InitializeField(ref _qAForm, nameof(QAForm));
        private QAFormLink _qAForm;

        [EditorSequence(1)]
        [EntityRelationship(DeleteAction.Cascade)]
        public DigitalFormLink Form => InitializeField(ref _form, nameof(Form));
        private DigitalFormLink _form;

        [NullEditor]
        [Obsolete("Being Replaced by FormData", true)]
        public string QAData { get; set; }

        [NullEditor]
        public string FormData { get; set; }

        [NullEditor]
        public string? BlobData { get; set; }

        [NullEditor]
        [Obsolete("Being Replaced by FormCompleted", true)]
        public DateTime QACompleted { get; set; }

        [EditorSequence(2)]
        [Caption("Started")]
        [DateTimeEditor]
        public DateTime FormStarted { get; set; } = DateTime.MinValue;

        [EditorSequence(3)]
        [Caption("Completed")]
        [DateTimeEditor]
        public DateTime FormCompleted { get; set; }
        
        [EditorSequence(4)]
        [Caption("Processed")]
        [DateTimeEditor]
        public DateTime FormProcessed { get; set; }
        
        [EditorSequence(5)]
        [Caption("Cancelled")]
        [DateTimeEditor]
        public DateTime FormCancelled { get; set; }

        [NullEditor]
        [Obsolete("Being Replaced by FormCompletedBy")]
        public UserLink QACompletedBy => InitializeField(ref _qACompletedBy, nameof(QACompletedBy));
        private UserLink _qACompletedBy;

        [EditorSequence(3)]
        [Caption("User")]
        public UserLink FormCompletedBy => InitializeField(ref _formCompletedBy, nameof(FormCompletedBy));
        private UserLink _formCompletedBy;

        [NullEditor]
        [Obsolete("Replaced with Status", true)]
        public bool Processed { get; set; } = false;
        
        [NullEditor]
        public Location Location => InitializeField(ref _location, nameof(Location));
        private Location _location;

        public IDigitalFormDataModel CreateDataModel(DigitalFormVariable[] variables, Entity? parent = null)
        {
            var t = typeof(DigitalFormDataModel<,,>).MakeGenericType(typeof(TParent), typeof(TParentLink), GetType());
            if (parent != null)
                return (Activator.CreateInstance(t, parent, this, variables) as IDigitalFormDataModel)!;
            return (Activator.CreateInstance(t, Parent.ID, ID, variables) as IDigitalFormDataModel)!;
        }

        public Guid ParentID()
        {
            return Parent.ID;
        }

        public Type ParentType() => typeof(TParent);

        [DurationEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]
        public TimeSpan FormOpen { get; set; } = TimeSpan.Zero;

        [NullEditor]
        public long Sequence { get; set; }
    }
}