package main

import "encoding/json"

// --- Client-to-server message types ---

// AttachMsg requests attaching to a named tmux session.
type AttachMsg struct {
	Attach string `json:"attach"`
}

// ResizeMsg requests a PTY resize.
type ResizeMsg struct {
	Resize struct {
		Cols int `json:"cols"`
		Rows int `json:"rows"`
	} `json:"resize"`
}

// DetachMsg requests detaching from the current session.
type DetachMsg struct {
	Detach bool `json:"detach"`
}

// --- Server-to-client message types ---

// AttachedMsg confirms a successful attach.
type AttachedMsg struct {
	Attached string `json:"attached"`
}

// ErrorMsg reports an error to the client.
type ErrorMsg struct {
	Error string `json:"error"`
}

// ExitedMsg reports that a session's process has exited.
type ExitedMsg struct {
	Exited string `json:"exited"`
}

// ParseControlMessage unmarshals a JSON control message and returns the
// message kind and a pointer to the typed value. Returns ("invalid", nil)
// for unparseable JSON and ("unknown", nil) for unrecognised keys.
func ParseControlMessage(data []byte) (string, interface{}) {
	var raw map[string]json.RawMessage
	if err := json.Unmarshal(data, &raw); err != nil {
		return "invalid", nil
	}

	if _, ok := raw["attach"]; ok {
		var msg AttachMsg
		if err := json.Unmarshal(data, &msg); err != nil {
			return "invalid", nil
		}
		return "attach", &msg
	}

	if _, ok := raw["resize"]; ok {
		var msg ResizeMsg
		if err := json.Unmarshal(data, &msg); err != nil {
			return "invalid", nil
		}
		return "resize", &msg
	}

	if _, ok := raw["detach"]; ok {
		var msg DetachMsg
		if err := json.Unmarshal(data, &msg); err != nil {
			return "invalid", nil
		}
		return "detach", &msg
	}

	return "unknown", nil
}

// MarshalAttached returns JSON for an AttachedMsg.
func MarshalAttached(session string) []byte {
	b, _ := json.Marshal(AttachedMsg{Attached: session})
	return b
}

// MarshalError returns JSON for an ErrorMsg.
func MarshalError(msg string) []byte {
	b, _ := json.Marshal(ErrorMsg{Error: msg})
	return b
}

// MarshalExited returns JSON for an ExitedMsg.
func MarshalExited(session string) []byte {
	b, _ := json.Marshal(ExitedMsg{Exited: session})
	return b
}