package signer

import (
	"errors"
	"fmt"
	"unsafe"

	log "github.com/sirupsen/logrus"
	"golang.org/x/sys/unix"

	"git.cacert.org/cacert-gosigner/datastructures"
	"git.cacert.org/cacert-gosigner/shared"
)

// The CommandProcessor takes parsed protocol data and executes the actual
// functionality.
type CommandProcessor struct {
}

// Process the signer request
func (p *CommandProcessor) Process(command datastructures.SignerRequest) (
	response *datastructures.SignerResponse,
	err error,
) {
	log.Infof("analyze %+v", command)

	switch command.Action {
	case shared.ActionNul:
		response, err = p.handleNulAction(command)
		return
	case shared.ActionSign:
		response, err = p.handleSignAction(command)
		return
	case shared.ActionRevoke:
		response, err = p.handleRevokeAction(command)
		return
	default:
		return nil, errors.New(fmt.Sprintf(
			"unsupported Action 0x%02x %s",
			int(command.Action),
			command.Action,
		))
	}
}

func (*CommandProcessor) handleNulAction(command datastructures.SignerRequest) (
	*datastructures.SignerResponse,
	error,
) {
	var timeSpec unix.Timespec
	err := unix.ClockGettime(unix.CLOCK_REALTIME, &timeSpec)
	if err != nil {
		log.Errorf("could not get system time: %v", err)
	}
	log.Debugf("current system time is %v", timeSpec)
	// TODO: calculate the actual system time from the payload
	_, _, e1 := unix.Syscall(
		unix.SYS_CLOCK_SETTIME,
		uintptr(unix.CLOCK_REALTIME),
		uintptr(unsafe.Pointer(&timeSpec)),
		0,
	)
	if e1 != 0 {
		log.Errorf("could not set system time: %v", e1)
	}

	return &datastructures.SignerResponse{
		Version: command.Version, Action: command.Action,
		Content1: "", Content2: "", Content3: ""}, nil
}

func (p *CommandProcessor) handleSignAction(
	command datastructures.SignerRequest,
) (
	*datastructures.SignerResponse,
	error,
) {
	log.Debugf("handle sign call: %v", command)
	return nil, errors.New("not implemented yet")
}

func (p *CommandProcessor) handleRevokeAction(
	command datastructures.SignerRequest,
) (
	*datastructures.SignerResponse,
	error,
) {
	log.Debugf("handle revoke call: %v", command)
	return nil, errors.New("not implemented yet")
}