# This is the replacement install_talkkonnect_with_config() function
# Copy this into setup_intercom.sh starting at line 197

install_talkkonnect_with_config() {
    local server_addr="$1"
    local server_port="$2"
    local tk_user="$3"
    local tk_pass="$4"
    local tk_channel="$5"

    echo
    echo "═══════════════════════════════════════════════════════════════"
    echo "   INSTALLING TALKKONNECT CLIENT"
    echo "═══════════════════════════════════════════════════════════════"
    echo
    echo "Using proven installation method (same as talkkonnect_complete_install.sh)..."
    echo

    # Get target user info
    local TARGET_USER="$KIOSK_USER"
    local TARGET_UID=$(id -u "$TARGET_USER")
    local TARGET_HOME="/home/$TARGET_USER"
    local CONFIG_DIR="$TARGET_HOME/.config/talkkonnect"

    # Verify home directory exists
    if [ ! -d "$TARGET_HOME" ]; then
        log_error "Home directory does not exist: $TARGET_HOME"
        pause
        return 1
    fi

    # --- System Prep ------------------------------------------------------
    echo "[1/7] Installing system dependencies..."
    sudo apt update
    sudo apt install -y wget git build-essential pkg-config \
        libasound2-dev libopus-dev libopus0 libopusfile-dev \
        libpipewire-0.3-dev libevdev-dev libopenal-dev alsa-utils

    # --- Go Installation --------------------------------------------------
    echo "[2/7] Installing Go 1.24.1..."
    if ! command -v go &>/dev/null || ! go version | grep -q "go1.24"; then
        sudo rm -rf /usr/local/go
        wget -q https://go.dev/dl/go1.24.1.linux-amd64.tar.gz
        sudo tar -C /usr/local -xzf go1.24.1.linux-amd64.tar.gz
        rm -f go1.24.1.linux-amd64.tar.gz
        sudo ln -sf /usr/local/go/bin/go /usr/bin/go
        export PATH="/usr/local/go/bin:$PATH"
        log_success "Go 1.24.1 installed"
    else
        log_success "Go already installed"
    fi

    # --- Clone TalkKonnect ------------------------------------------------
    echo "[3/7] Cloning talkkonnect repository..."
    cd ~
    if [ -d "talkkonnect" ]; then
        rm -rf talkkonnect
    fi
    git clone https://github.com/talkkonnect/talkkonnect.git
    cd talkkonnect

    # --- Patch gopus for x86_64 -------------------------------------------
    echo "[4/7] Applying x86_64 Opus patch..."
    go mod vendor

    if [ -d "vendor/github.com/talkkonnect/gopus" ]; then
        cat > vendor/github.com/talkkonnect/gopus/opus_nonshared.go << 'EOFOPUS'
// +build amd64,cgo 386,cgo

package gopus

// #cgo pkg-config: opus
// #cgo LDFLAGS: -lm
//
// #include <stdio.h>
// #include <stdlib.h>
// #include <opus.h>
//
// enum {
//   gopus_ok = OPUS_OK,
//   gopus_bad_arg = OPUS_BAD_ARG,
//   gopus_small_buffer = OPUS_BUFFER_TOO_SMALL,
//   gopus_internal = OPUS_INTERNAL_ERROR,
//   gopus_invalid_packet = OPUS_INVALID_PACKET,
//   gopus_unimplemented = OPUS_UNIMPLEMENTED,
//   gopus_invalid_state = OPUS_INVALID_STATE,
//   gopus_alloc_fail = OPUS_ALLOC_FAIL,
// };
//
// enum {
//   gopus_application_voip    = OPUS_APPLICATION_VOIP,
//   gopus_application_audio   = OPUS_APPLICATION_AUDIO,
//   gopus_restricted_lowdelay = OPUS_APPLICATION_RESTRICTED_LOWDELAY,
//   gopus_bitrate_max         = OPUS_BITRATE_MAX,
// };
//
// void gopus_setvbr(OpusEncoder *encoder, int vbr) {
//   opus_encoder_ctl(encoder, OPUS_SET_VBR(vbr));
// }
//
// void gopus_setbitrate(OpusEncoder *encoder, int bitrate) {
//   opus_encoder_ctl(encoder, OPUS_SET_BITRATE(bitrate));
// }
//
// opus_int32 gopus_bitrate(OpusEncoder *encoder) {
//   opus_int32 bitrate;
//   opus_encoder_ctl(encoder, OPUS_GET_BITRATE(&bitrate));
//   return bitrate;
// }
//
// void gopus_setapplication(OpusEncoder *encoder, int application) {
//   opus_encoder_ctl(encoder, OPUS_SET_APPLICATION(application));
// }
//
// opus_int32 gopus_application(OpusEncoder *encoder) {
//   opus_int32 application;
//   opus_encoder_ctl(encoder, OPUS_GET_APPLICATION(&application));
//   return application;
// }
//
// void gopus_encoder_resetstate(OpusEncoder *encoder) {
//   opus_encoder_ctl(encoder, OPUS_RESET_STATE);
// }
//
// void gopus_decoder_resetstate(OpusDecoder *decoder) {
//   opus_decoder_ctl(decoder, OPUS_RESET_STATE);
// }
import "C"

import (
	"errors"
	"unsafe"
)

type Application int

const (
	Voip               Application = C.gopus_application_voip
	Audio              Application = C.gopus_application_audio
	RestrictedLowDelay Application = C.gopus_restricted_lowdelay
)

const (
	BitrateMaximum = C.gopus_bitrate_max
)

type Encoder struct {
	data     []byte
	cEncoder *C.struct_OpusEncoder
}

func NewEncoder(sampleRate, channels int, application Application) (*Encoder, error) {
	encoder := &Encoder{}
	encoder.data = make([]byte, int(C.opus_encoder_get_size(C.int(channels))))
	encoder.cEncoder = (*C.struct_OpusEncoder)(unsafe.Pointer(&encoder.data[0]))

	ret := C.opus_encoder_init(encoder.cEncoder, C.opus_int32(sampleRate), C.int(channels), C.int(application))
	if err := getErr(ret); err != nil {
		return nil, err
	}
	return encoder, nil
}

func (e *Encoder) Encode(pcm []int16, frameSize, maxDataBytes int) ([]byte, error) {
	pcmPtr := (*C.opus_int16)(unsafe.Pointer(&pcm[0]))

	data := make([]byte, maxDataBytes)
	dataPtr := (*C.uchar)(unsafe.Pointer(&data[0]))

	encodedC := C.opus_encode(e.cEncoder, pcmPtr, C.int(frameSize), dataPtr, C.opus_int32(len(data)))
	encoded := int(encodedC)

	if encoded < 0 {
		return nil, getErr(C.int(encodedC))
	}
	return data[0:encoded], nil
}

func (e *Encoder) SetVbr(vbr bool) {
	var cVbr C.int
	if vbr {
		cVbr = 1
	} else {
		cVbr = 0
	}
	C.gopus_setvbr(e.cEncoder, cVbr)
}

func (e *Encoder) SetBitrate(bitrate int) {
	C.gopus_setbitrate(e.cEncoder, C.int(bitrate))
}

func (e *Encoder) Bitrate() int {
	return int(C.gopus_bitrate(e.cEncoder))
}

func (e *Encoder) SetApplication(application Application) {
	C.gopus_setapplication(e.cEncoder, C.int(application))
}

func (e *Encoder) Application() Application {
	return Application(C.gopus_application(e.cEncoder))
}

func (e *Encoder) ResetState() {
	C.gopus_encoder_resetstate(e.cEncoder)
}

type Decoder struct {
	data     []byte
	cDecoder *C.struct_OpusDecoder
	channels int
}

func NewDecoder(sampleRate, channels int) (*Decoder, error) {
	decoder := &Decoder{}
	decoder.data = make([]byte, int(C.opus_decoder_get_size(C.int(channels))))
	decoder.cDecoder = (*C.struct_OpusDecoder)(unsafe.Pointer(&decoder.data[0]))

	ret := C.opus_decoder_init(decoder.cDecoder, C.opus_int32(sampleRate), C.int(channels))
	if err := getErr(ret); err != nil {
		return nil, err
	}
	decoder.channels = channels

	return decoder, nil
}

func (d *Decoder) Decode(data []byte, frameSize int, fec bool) ([]int16, error) {
	var dataPtr *C.uchar
	if len(data) > 0 {
		dataPtr = (*C.uchar)(unsafe.Pointer(&data[0]))
	}
	dataLen := C.opus_int32(len(data))

	output := make([]int16, d.channels*frameSize)
	outputPtr := (*C.opus_int16)(unsafe.Pointer(&output[0]))

	var cFec C.int
	if fec {
		cFec = 1
	} else {
		cFec = 0
	}

	cRet := C.opus_decode(d.cDecoder, dataPtr, dataLen, outputPtr, C.int(frameSize), cFec)
	ret := int(cRet)

	if ret < 0 {
		return nil, getErr(cRet)
	}
	return output[:ret*d.channels], nil
}

func (d *Decoder) ResetState() {
	C.gopus_decoder_resetstate(d.cDecoder)
}

func GetSamplesPerFrame(data []byte, samplingRate int) (int, error) {
	dataPtr := (*C.uchar)(unsafe.Pointer(&data[0]))
	cSamplingRate := C.opus_int32(samplingRate)
	cRet := C.opus_packet_get_samples_per_frame(dataPtr, cSamplingRate)
	return int(cRet), nil
}

func CountFrames(data []byte) (int, error) {
	dataPtr := (*C.uchar)(unsafe.Pointer(&data[0]))
	cLen := C.opus_int32(len(data))

	cRet := C.opus_packet_get_nb_frames(dataPtr, cLen)
	if err := getErr(cRet); err != nil {
		return 0, err
	}
	return int(cRet), nil
}

var (
	ErrBadArgument   = errors.New("bad argument")
	ErrSmallBuffer   = errors.New("buffer is too small")
	ErrInternal      = errors.New("internal error")
	ErrInvalidPacket = errors.New("invalid packet")
	ErrUnimplemented = errors.New("unimplemented")
	ErrInvalidState  = errors.New("invalid state")
	ErrAllocFail     = errors.New("allocation failed")
	ErrUnknown       = errors.New("unknown error")
)

func getErr(code C.int) error {
	switch code {
	case C.gopus_ok:
		return nil
	case C.gopus_bad_arg:
		return ErrBadArgument
	case C.gopus_small_buffer:
		return ErrSmallBuffer
	case C.gopus_internal:
		return ErrInternal
	case C.gopus_invalid_packet:
		return ErrInvalidPacket
	case C.gopus_unimplemented:
		return ErrUnimplemented
	case C.gopus_invalid_state:
		return ErrInvalidState
	case C.gopus_alloc_fail:
		return ErrAllocFail
	default:
		return ErrUnknown
	}
}
EOFOPUS
        log_success "Opus patch applied"
    fi

    # --- Build TalkKonnect ------------------------------------------------
    echo "[5/7] Building talkkonnect (this may take a few minutes)..."
    cd ~/talkkonnect/cmd/talkkonnect

    export CGO_ENABLED=1
    export CGO_CFLAGS="$(pkg-config --cflags opus)"
    export CGO_LDFLAGS="$(pkg-config --libs opus) -lm"

    go build -mod=vendor -v -o ~/talkkonnect-binary . 2>&1 | tail -20

    if [ ! -f ~/talkkonnect-binary ]; then
        log_error "Build failed!"
        pause
        return 1
    fi

    # Stop any running instances
    if systemctl is-active --quiet talkkonnect 2>/dev/null; then
        sudo systemctl stop talkkonnect
    fi
    if pgrep -x talkkonnect > /dev/null; then
        sudo pkill -9 talkkonnect
        sleep 1
    fi

    # Install binary
    sudo cp ~/talkkonnect-binary /usr/local/bin/talkkonnect
    sudo chmod +x /usr/local/bin/talkkonnect
    rm ~/talkkonnect-binary
    log_success "Binary installed to /usr/local/bin/talkkonnect"

    # --- User Permissions -------------------------------------------------
    echo "[6/7] Setting up permissions..."
    if ! groups "$TARGET_USER" | grep -q input; then
        sudo usermod -a -G input "$TARGET_USER"
        log_success "Added $TARGET_USER to 'input' group"
    fi
    if ! groups "$TARGET_USER" | grep -q audio; then
        sudo usermod -a -G audio "$TARGET_USER"
        log_success "Added $TARGET_USER to 'audio' group"
    fi

    # --- Configuration ----------------------------------------------------
    echo "[7/7] Creating configuration..."

    # Create config directory as target user
    if [ "$TARGET_USER" != "$USER" ]; then
        sudo -u "$TARGET_USER" mkdir -p "$CONFIG_DIR"
    else
        mkdir -p "$CONFIG_DIR"
    fi

    # Create config file with provided settings
    sudo tee "$CONFIG_DIR/talkkonnect.xml" > /dev/null <<EOFXML
<?xml version="1.0" encoding="UTF-8"?>
<document type="talkkonnect/xml">
  <global>
    <software>
      <settings outputdevice="default"
                logfilenameandpath="$CONFIG_DIR/talkkonnect.log"
                logging="both"
                daemonize="false"
                cancelconnect="false"
                simplexwithvox="false"
                nextserverindex="0"/>
      <autoprovisioning enabled="false"/>
    </software>
    <hardware>
      <settings targetboard="pc" voiceactivitytimersecs="200"/>
      <io>
        <pins enabled="false"/>
      </io>
    </hardware>
  </global>

  <accounts>
    <account name="default" default="true">
      <serverandport>$server_addr:$server_port</serverandport>
      <username>$tk_user</username>
      <password>$tk_pass</password>
      <insecure>true</insecure>
      <register>false</register>
      <certificate></certificate>
      <channel>$tk_channel</channel>
      <ident></ident>
      <tokens enabled="false"></tokens>
      <voicetargets enabled="false">
        <id id="1" iscurrent="false" name="default">
          <channels></channels>
          <users></users>
        </id>
      </voicetargets>
    </account>
  </accounts>

  <beacon enabled="false"/>

  <audio>
    <input>
      <settings enabled="true" device="default" samplerate="48000"
                channels="1" codec="opus" framespersecond="50"/>
    </input>
    <output>
      <settings enabled="true" device="default" samplerate="48000" channels="1"/>
    </output>
  </audio>

  <ptt enabled="false">
    <usbkeyboard enabled="false"/>
  </ptt>

  <voiceactivity enabled="true">
    <settings threshold="0.3" holdtimems="1000" holdtimeoutms="2000"/>
  </voiceactivity>

  <sounds enabled="false"/>
  <txtts enabled="false"/>
  <smtp enabled="false"/>
  <api enabled="false"/>
  <printxml enabled="false"/>

</document>
EOFXML

    # Set ownership
    sudo chown -R "$TARGET_USER:$TARGET_USER" "$CONFIG_DIR"
    sudo chmod 755 "$CONFIG_DIR"
    sudo chmod 644 "$CONFIG_DIR/talkkonnect.xml"

    # Create systemd service
    sudo tee /etc/systemd/system/talkkonnect.service > /dev/null <<EOFSVC
[Unit]
Description=TalkKonnect Headless Mumble Transceiver
After=network-online.target sound.target
Wants=network-online.target

[Service]
Type=simple
User=$TARGET_USER
Group=$TARGET_USER
WorkingDirectory=$TARGET_HOME
ExecStart=/usr/local/bin/talkkonnect -config $CONFIG_DIR/talkkonnect.xml
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
Environment="XDG_RUNTIME_DIR=/run/user/$TARGET_UID"

[Install]
WantedBy=multi-user.target
EOFSVC

    sudo systemctl daemon-reload
    sudo systemctl enable talkkonnect
    sudo systemctl start talkkonnect

    sleep 3

    log_success "talkkonnect installed successfully!"
    echo "═══════════════════════════════════════════════════════════════"
    echo "  Server: $server_addr:$server_port"
    echo "  Username: $tk_user"
    echo "  Channel: $tk_channel"
    echo "  Config: $CONFIG_DIR/talkkonnect.xml"
    echo "  Binary: /usr/local/bin/talkkonnect"
    echo "═══════════════════════════════════════════════════════════════"
    echo

    # Show status
    if systemctl is-active --quiet talkkonnect; then
        log_success "Service is running"
        echo "View logs: sudo journalctl -u talkkonnect -f"
    else
        log_warning "Service may have issues"
        echo "Check logs: sudo journalctl -u talkkonnect -n 50"
    fi

    pause
}
