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

namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;

public class DetectorSlipsTime : DetectorAbstract
{
	protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
		=> CalcDeltaMinutes(telemetry, begin, end);

	protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
	{
		var currentPoint = telemetry[position];
		if (currentPoint.BitDepth < 150)
			return false;
		
		if (currentPoint.Pressure > 20)
			return false;

		var delta = currentPoint.WellDepth - currentPoint.BitDepth;
		if (delta < 0.1d)
			return false;

		var nextIndexPoint = telemetry.Length <= position ? position : position + 1;
		var nextPoint = telemetry[nextIndexPoint];
		var deltaBitDepth = Math.Abs(currentPoint.BitDepth - nextPoint.BitDepth);
		if (deltaBitDepth > 0.001d)
			return false;

		var deltaBlockPosition = Math.Abs(currentPoint.BlockPosition - nextPoint.BlockPosition);
		if (deltaBlockPosition < 0.001d)
			return false;

		return true;
	}

	protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
	{
		var currentPoint = telemetry[position];

		if (currentPoint.Pressure > 20)
			return IdReasonOfEnd_PressureIsHi;

		var prevPointIndex = position <= 0 ? 0 : position - 1;

		var prevPoint = telemetry[prevPointIndex];

		var deltaBitDepth = Math.Abs(currentPoint.BitDepth - prevPoint.BitDepth);

		if (deltaBitDepth > 0.001d && currentPoint.AxialLoad < currentPoint.HookWeight)
			return IdReasonOfEnd_ChangeBithDepthAndAxiloadLessHookWeight;

		return IdReasonOfEnd_NotDetected;
	}

	protected override (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry,
		int begin,
		int end)
	{
		return (WellOperationCategory.IdSlipsTime, new Dictionary<string, object>());
	}

	protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) =>
		Math.Abs((operationDetectorResult.Operation.DateStart - operationDetectorResult.Operation.DateEnd).TotalMinutes) < 30;
}