package api

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

type Console struct {
	AgentUuid UUID `json:"agent_uuid"`
	TokenUuid UUID `json:"token_uuid"`

	Uuid UUID   `json:"uuid"`
	Name string `json:"name"`
	Tag  string `json:"tag"`

	Type   ConsoleType `json:"type"`
	Status int         `json:"status"`

	Interval int    `json:"interval"`
	Env      string `json:"env"`
	Cwd      string `json:"cwd"`

	Rights map[string]bool `json:"rights"`

	CreatorUuid UUID `json:"creator_uuid"`
	LockerUuid  UUID `json:"locker_uuid"`
	OwnerUuid   UUID `json:"owner_uuid"`

	Created int64 `json:"created"`
	Updated int64 `json:"updated"`
}

func ConsoleNew(ctx context.Context, client IClient,
	args ConsoleNewArgs,
) (res Console, err error) {
	event, err := EventConsoleNew(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 ConsoleGet(ctx context.Context, client IClient,
	args ConsoleGetArgs,
) (res Console, err error) {
	event, err := EventConsoleGet(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 ConsoleGetByUuid(ctx context.Context, client IClient,
	uuid UUID,
) (res Console, err error) {
	event, err := EventConsoleGetByUuid(uuid)
	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 ConsoleGetByName(ctx context.Context, client IClient,
	agentUuid UUID, name string,
) (res Console, err error) {
	event, err := EventConsoleGetByName(agentUuid, name)
	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 ConsoleGetByTag(ctx context.Context, client IClient,
	agentUuid UUID, tag string,
) (res Console, err error) {
	event, err := EventConsoleGetByTag(agentUuid, tag)
	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 ConsoleListResult struct {
	Items  []Console `json:"items"`
	Tokens []UUID    `json:"tokens"`
}

func ConsoleGetList(ctx context.Context, client IClient,
	agentUuid UUID,
) (res ConsoleListResult, err error) {
	event, err := EventConsoleGetList(agentUuid)
	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 ConsoleSetType(ctx context.Context, client IClient,
	args ConsoleSetTypeArgs,
) (res Console, err error) {
	event, err := EventConsoleSetType(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 ConsoleSetInterval(ctx context.Context, client IClient,
	args ConsoleSetIntervalArgs,
) (res Console, err error) {
	event, err := EventConsoleSetInterval(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 ConsolePinTo(ctx context.Context, client IClient,
	args ConsolePinToArgs,
) (res Console, err error) {
	event, err := EventConsolePinTo(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 ConsoleLock(ctx context.Context, client IClient,
	args ConsoleLockArgs,
) (res Console, err error) {
	event, err := EventConsoleLock(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 ConsoleUnlock(ctx context.Context, client IClient,
	args ConsoleUnlockArgs,
) (res Console, err error) {
	event, err := EventConsoleUnlock(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 ConsoleOpen(ctx context.Context, client IClient,
	args ConsoleOpenArgs,
) (res Console, err error) {
	event, err := EventConsoleOpen(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 ConsoleClose(ctx context.Context, client IClient,
	args ConsoleCloseArgs,
) (res Console, err error) {
	event, err := EventConsoleClose(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 ConsoleDelete(ctx context.Context, client IClient,
	args ConsoleDeleteArgs,
) error {
	event, err := EventConsoleDelete(args)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

type ConsoleOutputResult struct {
	Console Console             `json:"console"`
	Items   []ConsoleOutputItem `json:"items"`

	NextPage struct {
		Offset int64 `json:"offset"`
		Limit  int64 `json:"limit"`
		Exist  bool  `json:"exist"`
	} `json:"next_page"`
}

type ConsoleOutputItem struct {
	Id          int64  `json:"id"`
	ConsoleUuid UUID   `json:"console_uuid"`
	AgentUuid   UUID   `json:"agent_uuid"`
	TokenUuid   UUID   `json:"token_uuid"`
	Status      int    `json:"status"`
	Uuid        UUID   `json:"uuid"`
	Line        string `json:"line"`
	LineIndex   int64  `json:"line_index"`
	Created     int64  `json:"created"`
}

func ConsoleGetOutput(ctx context.Context, client IClient,
	args ConsoleGetOutputArgs,
) (res ConsoleOutputResult, err error) {
	event, err := EventConsoleGetOutput(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 ConsoleSendInputResult struct {
	Console     Console `json:"console"`
	CommandUuid UUID    `json:"command_uuid"`
}

func ConsoleSendInput(ctx context.Context, client IClient,
	args ConsoleSendInputArgs,
) (res ConsoleSendInputResult, err error) {
	event, err := EventConsoleSendInput(args)
	if err != nil {
		return res, err
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type ConsoleInputOperatorItem struct {
	Id          int64                `json:"id"`
	ConsoleUuid UUID                 `json:"console_uuid"`
	AgentUuid   UUID                 `json:"agent_uuid"`
	TokenUuid   UUID                 `json:"token_uuid"`
	OwnerUuid   UUID                 `json:"owner_uuid"`
	Status      ConsoleCommandStatus `json:"status"`
	Uuid        UUID                 `json:"uuid"`
	Command     string               `json:"command"`
	Created     int64                `json:"created"`
	Updated     int64                `json:"updated"`
}

type ConsoleInputOperatorResult struct {
	Console Console                    `json:"console"`
	Items   []ConsoleInputOperatorItem `json:"items"`

	NextPage struct {
		Offset int64 `json:"offset"`
		Limit  int64 `json:"limit"`
		Exist  bool  `json:"exist"`
	} `json:"next_page"`
}

func ConsoleGetInputOperator(ctx context.Context, client IClient,
	args ConsoleGetInputOperatorArgs,
) (res ConsoleInputOperatorResult, err error) {
	event, err := EventConsoleGetInputOperator(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 PrivateConsoleAddUser(ctx context.Context, client IClient,
	args PrivateConsoleAddUserArgs,
) error {
	event, err := EventPrivateConsoleAddUser(args)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

func PrivateConsoleDeleteUser(ctx context.Context, client IClient,
	args PrivateConsoleDeleteUserArgs,
) error {
	event, err := EventPrivateConsoleDeleteUser(args)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

type ConsoleUser struct {
	User
	EditorRights map[string]bool `json:"console_editor_rights"`
	Rights       map[string]bool `json:"console_rights"`
}

func PrivateConsoleGetUser(ctx context.Context, client IClient,
	args PrivateConsoleGetUserArgs,
) (res ConsoleUser, err error) {
	event, err := EventPrivateConsoleGetUser(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 PrivateConsoleListUsers(ctx context.Context, client IClient,
	args PrivateConsoleListUsersArgs,
) (res []ConsoleUser, err error) {
	event, err := EventPrivateConsoleListUsers(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 PrivateConsoleUpdateUser(ctx context.Context, client IClient,
	args PrivateConsoleUpdateUserArgs,
) (res ConsoleUser, err error) {
	event, err := EventPrivateConsoleUpdateUser(args)
	if err != nil {
		return res, err
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func PrivateConsoleAddUserGroup(ctx context.Context, client IClient,
	args PrivateConsoleAddUserGroupArgs,
) error {
	event, err := EventPrivateConsoleAddUserGroup(args)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

func PrivateConsoleDeleteUserGroup(ctx context.Context, client IClient,
	args PrivateConsoleDeleteUserGroupArgs,
) error {
	event, err := EventPrivateConsoleDeleteUserGroup(args)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

type ConsoleUserGroup struct {
	UserGroup
	EditorRights map[string]bool `json:"console_editor_rights"`
	Rights       map[string]bool `json:"console_rights"`
}

func PrivateConsoleGetUserGroup(ctx context.Context, client IClient,
	args PrivateConsoleGetUserGroupArgs,
) (res ConsoleUserGroup, err error) {
	event, err := EventPrivateConsoleGetUserGroup(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 PrivateConsoleListUserGroups(ctx context.Context, client IClient,
	args PrivateConsoleListUserGroupsArgs,
) (res []ConsoleUserGroup, err error) {
	event, err := EventPrivateConsoleListUserGroups(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 PrivateConsoleUpdateUserGroup(ctx context.Context, client IClient,
	args PrivateConsoleUpdateUserGroupArgs,
) (res ConsoleUserGroup, err error) {
	event, err := EventPrivateConsoleUpdateUserGroup(args)
	if err != nil {
		return res, err
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}
