/*
DESCRIPTION
  file.go provides an implementation of the AVDevice interface for media files.

AUTHORS
  Saxon A. Nelson-Milton <saxon@ausocean.org>

LICENSE
  Copyright (C) 2019 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
  in gpl.txt.  If not, see http://www.gnu.org/licenses.
*/

package file

import (
	"errors"
	"fmt"
	"io"
	"os"

	"bitbucket.org/ausocean/av/revid/config"
)

// AVFile is an implementation of the AVDevice interface for a file containg
// audio or video data.
type AVFile struct {
	f   io.ReadCloser
	cfg config.Config
}

// NewAVFile returns a new AVFile.
func New() *AVFile { return &AVFile{} }

// Name returns the name of the device.
func (m *AVFile) Name() string {
	return "File"
}

// Set simply sets the AVFile's config to the passed config.
func (m *AVFile) Set(c config.Config) error {
	m.cfg = c
	return nil
}

// Start will open the file at the location of the InputPath field of the
// config struct.
func (m *AVFile) Start() error {
	var err error
	m.f, err = os.Open(m.cfg.InputPath)
	if err != nil {
		return fmt.Errorf("could not open media file: %w", err)
	}
	return nil
}

// Stop will close the file such that any further reads will fail.
func (m *AVFile) Stop() error { return m.f.Close() }

// Read implements io.Reader. If start has not been called, or Start has been
// called and Stop has since been called, an error is returned.
func (m *AVFile) Read(p []byte) (int, error) {
	if m.f != nil {
		return m.f.Read(p)
	}
	return 0, errors.New("AV file is closed")
}