using detect.device.Utils;
using Newtonsoft.Json;

namespace detect.device;

public class DeviceEvent
{
    public const string EventAnalyzerData = "event_analyzer_data";
    public const string EventDeviceConnected = "event_device_connected";
    public const string EventDeviceDisConnected = "event_device_disconnected";
    
    public string Name { get; set; }
    public IDictionary<string, object> Result { get; set; }
}

public class DeviceClientRequestBuilder
{
    private readonly Dictionary<string, object> _params = new();
    public readonly string RequestId = Guid.NewGuid().ToString();
    private string? _type;
    private string? _component;
    private string? _method;
    
    public static DeviceClientRequestBuilder Create()
    {
        return new DeviceClientRequestBuilder();
    }

    public DeviceClientRequestBuilder WithType(string type)
    {
        this._type = type;
        return this;
    }
    
    public DeviceClientRequestBuilder WithComponent(string component)
    {
        this._component = component;
        return this;
    }
    
    public DeviceClientRequestBuilder WithMethod(string method)
    {
        this._method = method;
        return this;
    }
    
    public DeviceClientRequestBuilder WithParam(string name, object value)
    {
        this._params.TryAdd(name, value);
        return this;
    }
    
    public DeviceClientRequestBuilder WithParams(Dictionary<string, object> dictionary)
    {
        foreach (var (key, value) in dictionary)
        {
            this._params.TryAdd(key, value);
        }
        return this;
    }
    
    public string Build()
    {
        Dictionary<string, object?> request = new()
        {
            ["requestId"] = RequestId,
            ["type"] = _type,
            ["component"] = _component,
            ["method"] = _method,
            ["params"] = _params
        };
        return JsonUtil.SerializeObject(request);
    }
}

public class DeviceClientResponse<TResult>
{
    public DeviceClientResponse(int code, string message)
    {
        Code = code;
        Message = message;
    }
    
    public string? RequestId { get; set; }
    /// <summary>
    /// 回复类型，service，task，event
    /// </summary>
    public string Type { get; set; } = "service";
    public int Code { get; set; }
    public string Message { get; set; }
    public double? Duration { get; set; }
    public TResult? Result { get; set; }
    public bool IsSuccess => this.Code == 0;
    public bool IsFailed => this.Code != 0;
}

public interface IDeviceClient
{
    public event EventHandler<DeviceEvent> DeviceEvent;

    public bool Connected();
    
    public bool ConnectAsync();
    
    public bool DisConnectAsync();
    
    public void PublishEvent(DeviceEvent deviceEvent);
    
    public Task<DeviceClientResponse<T>> RequestAction<T>(DeviceClientRequestBuilder builder);
    
    public DeviceClientResponse<object> RequestActionSync(DeviceClientRequestBuilder builder);
}