/*
NAME
  RTMP.go

DESCRIPTION
  See Readme.md

AUTHOR
  Saxon Nelson-Milton <saxon@ausocean.org>

LICENSE
  RTMP.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)

  It is free software: you can redistribute it and/or modify them
  under the terms of the GNU General Public License as published by the
  Free Software Foundation, either version 3 of the License, or (at your
  option) any later version.

  It is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 for more details.

  You should have received a copy of the GNU General Public License
  along with revid in gpl.txt.  If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
package rtmp

// #cgo CFLAGS: -I/home/pi/go/src/bitbucket.org/AusOcean/av/rtmp/
// #cgo CFLAGS: -I/home/pi/go/src/bitbucket.org/ausocean/av/rtmp/rtmp_c/librtmp
// #cgo LDFLAGS: /home/pi/go/src/bitbucket.org/ausocean/av/rtmp/rtmp_c/librtmp/librtmp.a
// #cgo LDFLAGS: -lz
// #include <RTMPWrapper.h>
import "C"

import (
	"errors"
	_ "fmt"
	"sync"
	"unsafe"
	"bitbucket.org/ausocean/av/tools"
)

// RTMPSession provides a crude interface for sending flv tags over rtmp
type RTMPSession interface {
	StartSession() error
	WriteFrame(data []byte, dataLength uint) error
	EndSession() error
}

// rtmpSession provides parameters required for an rtmp communication session
type rtmpSession struct {
	url     string
	timeout uint
	running bool
	mutex   *sync.Mutex
}

// NewRTMPSession returns a new instance of an rtmpSession struct
func NewRTMPSession(url string, connectTimeout uint) (session *rtmpSession) {
	session = new(rtmpSession)
	session.url = url
	session.timeout = connectTimeout
	session.mutex = &sync.Mutex{}
	return
}

// StartSession establishes an rtmp connection with the url passed into the
// constructor
func (s *rtmpSession) StartSession() error {
	if !s.running {
		if !tools.UintToBool(uint(C.RTMP_start_session(C.CString(s.url), C.uint(s.timeout)))) {
			return errors.New("RTMP start error! Check rtmp log for details!")
		}
		s.running = true
	} else {
		return errors.New("Tried to start rtmp session, but already started!")
	}
	return nil
}

// WriteFrame writes a frame (flv tag) to the rtmp connection
// TODO: Remove mutex
func (s *rtmpSession) WriteFrame(data []byte, dataLength uint) error {
	if s.running {
		dataCopy := make([]byte, len(data))
		copy(dataCopy, data)
		if !tools.UintToBool(uint(C.RTMP_write_frame((*C.char)(unsafe.Pointer(&dataCopy[0])), C.uint(dataLength)))) {
			return errors.New("RTMP write error! Check rtmp log for details!")
		}
	} else {
		return errors.New("RTMP session not running, can't write!")
	}
	return nil
}

// EndSession terminates the rtmp connection
func (s *rtmpSession) EndSession() error {
	if s.running {
		s.running = false
		if !tools.UintToBool(uint(C.RTMP_end_session())) {
			return errors.New("RTMP end session error! Check rtmp log for details!")
		}
	} else {
		return errors.New("Tried to stop rtmp session, but not running!")
	}
	return nil
}