using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsHerbicide.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using static FarmmapsApi.Extensions;
using static FarmmapsApiSamples.Constants;

namespace FarmmapsHerbicide
{
    public class HerbicideService
    {
        private readonly ILogger<HerbicideService> _logger;
        private readonly FarmmapsApiService _farmmapsApiService;
        private readonly GeneralService _generalService;

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

        public async Task<List<HerbicideAgent>> GetHerbicideAgents()
        {
            var itemType = "vnd.farmmaps.package.vra.herbicide";
            var vraHerbicideDataItems = await _farmmapsApiService.GetItemsAsync(string.Empty, itemType);

            var item = vraHerbicideDataItems.FirstOrDefault();
            if (item == null)
                return null;

            return item.Data.ContainsKey("agents") ? item.Data["agents"].ToObject<List<HerbicideAgent>>() : null;
        }

        public async Task<Item> CalculateApplicationMapAsync(Item cropfieldItem, HerbicideAgent agent, params Item[] inputItem)
        {
            if (inputItem.Length == 0)
                return null;
            
            var taskRequest = new TaskRequest()
            {
                TaskType = "vnd.farmmaps.task.vraherbicide"
            };
            taskRequest.attributes["inputCode"] = inputItem[0].Code;
            taskRequest.attributes["agent"] = JsonConvert.SerializeObject(agent);
            
            // check for the layer name
            taskRequest.attributes["inputLayerName"] = inputItem[0].Data["layers"][0]["name"].ToString();

            if (inputItem.Length > 1)
            {
                taskRequest.attributes["extraInputCode"] = inputItem[1].Code;
                taskRequest.attributes["extraInputLayerName"] = inputItem[1].Data["layers"][0]["name"].ToString();
            }

            var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
            await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
            {
                _logger.LogInformation("Checking vraherbicide task status");
                var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
                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 itemName = $"VRAHerbicide {agent.Name}";
            var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
                GEOTIFF_PROCESSED_ITEMTYPE, itemName, 
                i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
                            i.Name.ToLower().Contains(itemName.ToLower()));
            
            if (applianceMapItem == null)
            {
                _logger.LogError("Could not find the VRAHerbicide geotiff child item under cropfield");
                return null;
            }

            return applianceMapItem;
        }
    }
}