//
//  WalkManager.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands.Walking;
using NosSmooth.Core.Errors;
using Remora.Results;
namespace NosSmooth.Extensions.Pathfinding;
/// 
/// The walk manager using pathfinding to walk to given position.
/// 
public class WalkManager
{
    private readonly INostaleClient _client;
    private readonly Pathfinder _pathfinder;
    private readonly PathfinderState _state;
    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// The client.
    /// The pathfinder.
    /// The state.
    public WalkManager(INostaleClient client, Pathfinder pathfinder, PathfinderState state)
    {
        _client = client;
        _pathfinder = pathfinder;
        _state = state;
    }
    /// 
    /// Go to the given position.
    /// 
    /// 
    /// Expect  if the destination could not be reached.
    /// Expect  if the path could not be found.
    /// 
    /// The target x coordinate.
    /// The target y coordinate.
    /// Whether to allow user actions during the walk operation.
    /// The cancellation token used for cancelling the operation.
    /// The positions to walk pets to.
    /// A result that may not succeed.
    public async Task GoToAsync(short x, short y, bool allowUserActions = true, CancellationToken ct = default, params (int Selector, short TargetX, short TargetY)[] pets)
    {
        var pathResult = _pathfinder.FindPathFromCurrent(x, y);
        if (!pathResult.IsSuccess)
        {
            return Result.FromError(pathResult);
        }
        if (pathResult.Entity.Parts.Count == 0)
        {
            return Result.FromSuccess();
        }
        var path = pathResult.Entity;
        while (!path.ReachedEnd)
        {
            if (path.MapId != _state.MapId)
            {
                return new WalkNotFinishedError(_state.X, _state.Y, WalkUnfinishedReason.MapChanged);
            }
            var next = path.TakeForwardPath();
            var walkResult = await _client.SendCommandAsync(new WalkCommand(next.X, next.Y, pets, 2, AllowUserCancel: allowUserActions), ct);
            if (!walkResult.IsSuccess)
            {
                if (path.ReachedEnd && walkResult.Error is WalkNotFinishedError walkNotFinishedError
                    && walkNotFinishedError.Reason == WalkUnfinishedReason.MapChanged)
                {
                    return Result.FromSuccess();
                }
                if (_state.X == x && _state.Y == y)
                {
                    return Result.FromSuccess();
                }
                return walkResult;
            }
        }
        return Result.FromSuccess();
    }
}