package scpi

import "github.com/uopi/uopi/internal/datasource"

// Config is the [datasource.scpi] section. Each instrument is polled
// independently over its own TCP socket.
type Config struct {
	Enabled bool `toml:"enabled"`
	// PollIntervalMs is the default polling period for channels that do not
	// override it. Zero → 1000 ms.
	PollIntervalMs int          `toml:"poll_interval_ms"`
	Instruments    []Instrument `toml:"instruments"`
}

// Instrument is one SCPI device reachable over a raw TCP socket. Address is
// "host:port"; the conventional SCPI-raw port 5025 is appended if absent.
type Instrument struct {
	Name string `toml:"name"`
	// Transport selects the link type. "raw" (default) is line-based SCPI over
	// TCP. Reserved: "vxi11" (not yet implemented).
	Transport string `toml:"transport"`
	Address   string `toml:"address"`
	TimeoutMs int    `toml:"timeout_ms"`
	// Terminator is appended to every command. Empty → "\n".
	Terminator string    `toml:"terminator"`
	Channels   []Channel `toml:"channels"`
}

// Channel maps a SCPI query/command pair onto a signal named
// "instrument:channel".
type Channel struct {
	Name string `toml:"name"`
	// Query is the SCPI command whose response is the channel value,
	// e.g. "MEAS:VOLT?". Required.
	Query string `toml:"query"`
	// WriteCmd is a printf-style template used by Write; "%v" is replaced with
	// the value, e.g. "VOLT %v". Empty → channel is read-only.
	WriteCmd string `toml:"write_cmd"`
	// Type is the value type: "float" (default), "string", "int", or "bool".
	Type           string  `toml:"type"`
	Unit           string  `toml:"unit"`
	Min            float64 `toml:"min"`
	Max            float64 `toml:"max"`
	PollIntervalMs int     `toml:"poll_interval_ms"`
	Description    string  `toml:"description"`
}

func (c Channel) dataType() datasource.DataType {
	switch c.Type {
	case "string":
		return datasource.TypeString
	case "int":
		return datasource.TypeInt64
	case "bool":
		return datasource.TypeBool
	default:
		return datasource.TypeFloat64
	}
}

func (c Channel) writable() bool { return c.WriteCmd != "" }

func (c Channel) metadata(instrument string) datasource.Metadata {
	return datasource.Metadata{
		Name:        instrument + ":" + c.Name,
		Type:        c.dataType(),
		Unit:        c.Unit,
		Description: c.Description,
		DisplayLow:  c.Min,
		DisplayHigh: c.Max,
		DriveLow:    c.Min,
		DriveHigh:   c.Max,
		Writable:    c.writable(),
	}
}
