using System;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsHaulmkilling.Models;
using FarmmapsZonering.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using static FarmmapsApi.Extensions;
using static FarmmapsApiSamples.Constants;

namespace FarmmapsZonering.Services
{
    public class ZoneringService
    {
        private readonly ILogger<ZoneringService> _logger;
        private readonly FarmmapsApiService _farmmapsApiService;
        private readonly GeneralService _generalService;

        public ZoneringService(ILogger<ZoneringService> logger, FarmmapsApiService farmmapsApiService,
            GeneralService generalService)
        {
            _logger = logger;
            _farmmapsApiService = farmmapsApiService;
            _generalService = generalService;
        }

        public async Task<Item> CreateApplicationMapAsync(Item cropfieldItem, string formula, Output output, params InputParameter[] inputItemCodes)
        {
            var zoneringTaskRequest = new TaskRequest() {TaskType = VRAZONERING_TASK};
            zoneringTaskRequest.attributes["formula"] = formula;
            zoneringTaskRequest.attributes["output"] = JsonConvert.SerializeObject(output);
            zoneringTaskRequest.attributes["inputs"] = JsonConvert.SerializeObject(inputItemCodes);

            var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, zoneringTaskRequest);
            
            await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
            {
                var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
                _logger.LogInformation($"Waiting on calculation of application map; Status: {itemTaskStatus.State}");
                if (itemTaskStatus.IsFinished)
                    tokenSource.Cancel();
            });

            var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
            if (itemTask.State == ItemTaskState.Error)
            {
                _logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
                return null;
            }
            
            var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
                GEOTIFF_PROCESSED_ITEMTYPE, output.Name,
                i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
                     i.Name.ToLower().Contains(output.Name.ToLower()));

            if (applianceMapItem == null)
            {
                _logger.LogError("Could not find the VRAZonering geotiff child item under cropfield");
                return null;
            }

            return applianceMapItem;
        }
    }
}