using Edge.Core.Processor.Dispatcher;
using Edge.Core.Processor.Dispatcher.Attributes;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace Edge.Core.Processor
{
    public interface IProcessor
    {
        /// <summary>
        /// Gets the meta config name of this Processor instance created from.
        ///     this is unique guaranteed for instances.
        /// Framework will set this value at runtime.
        /// </summary>
        string MetaConfigName { get; set; }
        //string SerialNumber { get; set; }

        /// <summary>
        /// Framework does not guarantee the sequence of this call between all processors(include AppProcessor and DeviceProcessor).
        ///     For AppProcessor, the framework guarantees Init(...) for all AppProcessors have called at this stage, but the DeviceProcessor may or may not be started.
        /// </summary>
        /// <returns></returns>
        Task<bool> Start() { return Task.FromResult(true); }
        Task<bool> Stop() { return Task.FromResult(true); }
        //bool Destroy(string reason) { return true; }

        /// <summary>
        /// The method will be called from user for a generic test purpose, should implemented this method 
        /// to cover most real life time logic to give user a meaningful and confidence result for how this processor would work 
        /// when run for real.
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns>throw exception to indicates the test failed, otherwise, return a Completed task.</returns>
        Task Test(params object[] parameters) { throw new NotImplementedException("暂不支持测试"); }
    }

    public class ProcessorEqualityComparer : IEqualityComparer<IProcessor>
    {
        public bool Equals([AllowNull] IProcessor x, [AllowNull] IProcessor y)
        {
            if (x == null || y == null) return false;
            if (x.MetaConfigName != y.MetaConfigName) return false;
            //if (x.SerialNumber != y.SerialNumber) return false;
            if (x is IAppProcessor && !(y is IAppProcessor)) return false;
            if (y is IAppProcessor && !(x is IAppProcessor)) return false;
            return true;
        }

        public int GetHashCode([DisallowNull] IProcessor obj)
        {
            return obj.GetHashCode();
        }
    }

    /// <summary>
    /// the result for operating a processor's instance.
    /// </summary>
    public class ProcessorInstanceOperatingResult
    {
        public IProcessor ProcessorInstance { get; set; }
        public ProcessorMetaConfig MetaConfig { get; set; }
        //public string Description { get; set; }
        public bool Succeed { get; set; }

        /// <summary>
        /// the version of current assembly, in most case, it's the AppProcessor or DeviceProcessor's assembly version.
        /// </summary>
        public string HostVersion { get; set; }

        /// <summary>
        /// the version of the Edge.Core assembly.
        /// </summary>
        public string CoreVersion { get; set; }
        public string FailedReason { get; set; }
    }

    public class ProcessorLifeCycleOperationResult
    {
        public static ProcessorLifeCycleOperationResult From(ProcessorInstanceOperatingResult input)
        {
            var output = new ProcessorLifeCycleOperationResult();
            var metaPartsDescriptor = input.ProcessorInstance?.ProcessorDescriptor()?.DeviceHandlerOrApp?.GetType()
                    ?.GetCustomAttributes<MetaPartsDescriptor>()?.FirstOrDefault();
            output.Description = metaPartsDescriptor?.Description;
            output.IsSystemInternalComponent = metaPartsDescriptor?.IsSystemInternalComponent ?? false;
            output.ProcessorInstanceEntryName = input.MetaConfig?.Name;
            output.Tags = metaPartsDescriptor?.Tags;
            output.ProcessorMetaConfigName = input.MetaConfig?.Name;
            output.HostVersion = input.HostVersion;
            output.CoreVersion = input.CoreVersion;
            output.Succeed = input.Succeed;
            output.FailedReason = input.FailedReason;
            return output;
        }

        public string Description { get; set; }
        public string ProcessorMetaConfigName { get; set; }
        public string ProcessorInstanceEntryName { get; set; }
        /// <summary>
        /// the version of current assembly, in most case, it's the AppProcessor or DeviceProcessor's assembly version.
        /// </summary>
        public string HostVersion { get; set; }

        /// <summary>
        /// the version of the Edge.Core assembly.
        /// </summary>
        public string CoreVersion { get; set; }
        public bool IsSystemInternalComponent { get; set; }
        public bool Succeed { get; set; }
        public string FailedReason { get; set; }

        public string[] Tags { get; set; }
    }
}
