package api

import (
	"agent/client/events"
	"context"
	"encoding/json"
)

type AgentTunnelPortMode int

type TunnelPort struct {
	Uuid UUID `json:"uuid"`

	AgentUuid UUID `json:"agent_uuid"`

	Active bool `json:"active"`

	Host string `json:"host"`
	Port int    `json:"port"`

	Mode    AgentTunnelPortMode `json:"mode"`
	Encrypt bool                `json:"encrypt"`

	RHost string `json:"rhost"`
	RPort int    `json:"rport"`

	Note string `json:"note"`

	CreatorUuid UUID  `json:"creator_uuid"`
	Created     int64 `json:"created"`
	Updated     int64 `json:"updated"`

	PayloadUuid UUID `json:"payload_uuid"`
	SrvPort     int  `json:"srv_port"`
}

func TunnelOpenPort(ctx context.Context, client IClient,
	args TunnelOpenPortArgs, onResult ...events.OnResult,
) (res TunnelPort, err error) {
	event, err := EventTunnelOpenPort(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event, onResult...)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func TunnelListenPort(ctx context.Context, client IClient,
	args TunnelListenPortArgs, onResult ...events.OnResult,
) (res TunnelPort, err error) {
	event, err := EventTunnelListenPort(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event, onResult...)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func TunnelClosePort(ctx context.Context, client IClient,
	args TunnelClosePortArgs,
) (err error) {
	event, err := EventTunnelClosePort(args)
	if err != nil {
		return nil
	}
	_, err = client.Execute(ctx, event)
	return err
}

func TunnelGetPort(ctx context.Context, client IClient,
	args TunnelGetPortArgs,
) (res TunnelPort, err error) {
	event, err := EventTunnelGetPort(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type TunnelListPortsResult struct {
	NextPage NextPage     `json:"next_page"`
	Items    []TunnelPort `json:"items"`
}

func TunnelListPorts(ctx context.Context, client IClient,
	args TunnelListPortsArgs,
) (res TunnelListPortsResult, err error) {
	event, err := EventTunnelListPorts(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func TunnelListPortsByAgent(ctx context.Context, client IClient,
	args TunnelListPortsByAgentArgs,
) (res TunnelListPortsResult, err error) {
	event, err := EventTunnelListPortsByAgent(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func TunnelListPortsAll(ctx context.Context, client IClient,
	args TunnelListPortsAllArgs,
) (res TunnelListPortsResult, err error) {
	event, err := EventTunnelListPortsAll(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func TunnelUpdatePort(ctx context.Context, client IClient,
	args TunnelUpdatePortArgs,
) (res TunnelPort, err error) {
	event, err := EventTunnelUpdatePort(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}
