using AsbCloudApp.Data;
using AsbCloudDb.Model;
using System.Collections.Generic;
using System.Linq;

namespace AsbCloudInfrastructure.Services
{
    public class TelemetryOperationDetectorService
    {
        private readonly IEnumerable<TelemetryOperationDetector> detectors;

        public TelemetryOperationDetectorService(IEnumerable<WellOperationCategory> operations)
        {
            detectors = new List<TelemetryOperationDetector>()
            {
                new TelemetryOperationDetector
                {
                    Order = 1,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("На поверхности")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing
                                && data.IsBitPositionLt20 && data.IsHookWeightLt3;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 2,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Удержание в клиньях")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                               !data.IsBitPositionIncreasing && !data.IsBitPositionDecreasing &&
                                data.IsBlockPositionDecreasing && !data.IsBlockPositionIncreasing &&
                                data.IsHookWeightLt3;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 3,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Подъем с проработкой")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionDecreasing && data.IsBlockPositionDecreasing &&
                                data.IsRotorSpeedGt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 4,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Спуск с проработкой")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionIncreasing && data.IsBitPositionIncreasing &&
                                data.IsRotorSpeedGt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 5,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Подъем с промывкой")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionDecreasing && data.IsBitPositionDecreasing &&
                                data.IsRotorSpeedLt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 6,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Спуск с промывкой")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionIncreasing && data.IsBlockPositionIncreasing &&
                                data.IsRotorSpeedLt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 7,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Спуск в скважину")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionIncreasing && data.IsBlockPositionIncreasing &&
                                data.IsRotorSpeedLt3 && data.IsPressureLt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 8,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Спуск с вращением")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionIncreasing && data.IsBlockPositionIncreasing &&
                                data.IsRotorSpeedGt3 && data.IsPressureLt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 9,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Подъем из скважины")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionDecreasing && data.IsBlockPositionDecreasing &&
                                data.IsRotorSpeedLt3 && data.IsPressureLt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 10,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Подъем с вращением")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                                data.IsBitPositionDecreasing && data.IsBlockPositionDecreasing &&
                                data.IsRotorSpeedGt3 && data.IsPressureLt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 11,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Промывка в покое")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                               !data.IsBitPositionDecreasing && !data.IsBitPositionIncreasing &&
                               !data.IsBlockPositionDecreasing && !data.IsBlockPositionIncreasing &&
                               data.IsRotorSpeedLt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 12,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Промывка с вращением")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                               !data.IsBitPositionDecreasing && !data.IsBitPositionIncreasing &&
                               !data.IsBlockPositionDecreasing && !data.IsBlockPositionIncreasing &&
                               data.IsRotorSpeedGt3 && data.IsPressureGt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 13,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Неподвижное состояние")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                               !data.IsBitPositionDecreasing && !data.IsBitPositionIncreasing &&
                               !data.IsBlockPositionDecreasing && !data.IsBlockPositionIncreasing &&
                               data.IsRotorSpeedLt3 && data.IsPressureLt20 && data.IsHookWeightNotChanges;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 14,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Вращение без циркуляции")),
                    Detect = (data) =>
                    {
                        return !data.IsWellDepthDecreasing && !data.IsWellDepthIncreasing &&
                               !data.IsBitPositionDecreasing && !data.IsBitPositionIncreasing &&
                               !data.IsBlockPositionDecreasing && !data.IsBlockPositionIncreasing &&
                               data.IsRotorSpeedGt3 && data.IsPressureLt20;
                    }
                },
                new TelemetryOperationDetector
                {
                    Order = 15,
                    Operation = operations.FirstOrDefault(o => o.Name.Equals("Невозможно определить операцию")),
                    Detect = (data) => true
                }
            };
        }

        public WellOperationCategory DetectOperation(TelemetryAnalysisDto data) =>
            detectors.OrderBy(d => d.Order).First(o => o.Detect(data)).Operation
                ?? new WellOperationCategory { Id = 1, Name = "Невозможно определить операцию" };
    }
}