using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Lifestream.Enums;
using LightlessSync.Interop.Ipc.Framework;
using LightlessSync.Services.Mediator;
using Microsoft.Extensions.Logging;


namespace LightlessSync.Interop.Ipc;

public sealed class IpcCallerLifestream : IpcServiceBase
{
    private static readonly IpcServiceDescriptor LifestreamDescriptor = new("Lifestream", "Lifestream", new Version(0, 0, 0, 0));

    private readonly ICallGateSubscriber<string, object> _executeLifestreamCommand;
    private readonly ICallGateSubscriber<AddressBookEntryTuple, bool> _isHere;
    private readonly ICallGateSubscriber<AddressBookEntryTuple, object> _goToHousingAddress;
    private readonly ICallGateSubscriber<bool> _isBusy;
    private readonly ICallGateSubscriber<object> _abort;
    private readonly ICallGateSubscriber<string, bool> _changeWorld;
    private readonly ICallGateSubscriber<uint, bool> _changeWorldById;
    private readonly ICallGateSubscriber<string, bool> _aetheryteTeleport;
    private readonly ICallGateSubscriber<uint, bool> _aetheryteTeleportById;
    private readonly ICallGateSubscriber<bool> _canChangeInstance;
    private readonly ICallGateSubscriber<int> _getCurrentInstance;
    private readonly ICallGateSubscriber<int> _getNumberOfInstances;
    private readonly ICallGateSubscriber<int, object> _changeInstance;
    private readonly ICallGateSubscriber<(ResidentialAetheryteKind, int, int)> _getCurrentPlotInfo;

    public IpcCallerLifestream(IDalamudPluginInterface pi, LightlessMediator lightlessMediator, ILogger<IpcCallerLifestream> logger)
        : base(logger, lightlessMediator, pi, LifestreamDescriptor)
    {
        _executeLifestreamCommand = pi.GetIpcSubscriber<string, object>("Lifestream.ExecuteCommand");
        _isHere = pi.GetIpcSubscriber<AddressBookEntryTuple, bool>("Lifestream.IsHere");
        _goToHousingAddress = pi.GetIpcSubscriber<AddressBookEntryTuple, object>("Lifestream.GoToHousingAddress");
        _isBusy = pi.GetIpcSubscriber<bool>("Lifestream.IsBusy");
        _abort = pi.GetIpcSubscriber<object>("Lifestream.Abort");
        _changeWorld = pi.GetIpcSubscriber<string, bool>("Lifestream.ChangeWorld");
        _changeWorldById = pi.GetIpcSubscriber<uint, bool>("Lifestream.ChangeWorldById");
        _aetheryteTeleport = pi.GetIpcSubscriber<string, bool>("Lifestream.AetheryteTeleport");
        _aetheryteTeleportById = pi.GetIpcSubscriber<uint, bool>("Lifestream.AetheryteTeleportById");
        _canChangeInstance = pi.GetIpcSubscriber<bool>("Lifestream.CanChangeInstance");
        _getCurrentInstance = pi.GetIpcSubscriber<int>("Lifestream.GetCurrentInstance");
        _getNumberOfInstances = pi.GetIpcSubscriber<int>("Lifestream.GetNumberOfInstances");
        _changeInstance = pi.GetIpcSubscriber<int, object>("Lifestream.ChangeInstance");
        _getCurrentPlotInfo = pi.GetIpcSubscriber<(ResidentialAetheryteKind, int, int)>("Lifestream.GetCurrentPlotInfo");
        CheckAPI();
    }

    public void ExecuteLifestreamCommand(string command)
    {
        if (!APIAvailable) return;
        _executeLifestreamCommand.InvokeAction(command);
    }

    public bool IsHere(AddressBookEntryTuple entry)
    {
        if (!APIAvailable) return false;
        return _isHere.InvokeFunc(entry);
    }

    public void GoToHousingAddress(AddressBookEntryTuple entry)
    {
        if (!APIAvailable) return;
        _goToHousingAddress.InvokeAction(entry);
    }

    public bool IsBusy()
    {
        if (!APIAvailable) return false;
        return _isBusy.InvokeFunc();
    }

    public void Abort()
    {
        if (!APIAvailable) return;
        _abort.InvokeAction();
    }

    public bool ChangeWorld(string worldName)
    {
        if (!APIAvailable) return false;
        return _changeWorld.InvokeFunc(worldName);
    }

    public bool AetheryteTeleport(string aetheryteName)
    {
        if (!APIAvailable) return false;
        return _aetheryteTeleport.InvokeFunc(aetheryteName);
    }

    public bool ChangeWorldById(uint worldId)
    {
        if (!APIAvailable) return false;
        return _changeWorldById.InvokeFunc(worldId);
    }

    public bool AetheryteTeleportById(uint aetheryteId)
    {
        if (!APIAvailable) return false;
        return _aetheryteTeleportById.InvokeFunc(aetheryteId);
    }

    public bool CanChangeInstance()
    {
        if (!APIAvailable) return false;
        return _canChangeInstance.InvokeFunc();
    }
    public int GetCurrentInstance()
    {
        if (!APIAvailable) return -1;
        return _getCurrentInstance.InvokeFunc();
    }
    public int GetNumberOfInstances()
    {
        if (!APIAvailable) return -1;
        return _getNumberOfInstances.InvokeFunc();
    }
    public void ChangeInstance(int instanceNumber)
    {
        if (!APIAvailable) return;
        _changeInstance.InvokeAction(instanceNumber);
    }
    public (ResidentialAetheryteKind, int, int)? GetCurrentPlotInfo()
    {
        if (!APIAvailable) return (ResidentialAetheryteKind.None, -1, -1);
        return _getCurrentPlotInfo.InvokeFunc();
    }
}