// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package serial

import (
	"bufio"
	"context"
	"errors"
	"io"
	"io/ioutil"
	"net"
	"os"
	"time"

	"go.fuchsia.dev/fuchsia/tools/lib/logger"
)

// ErrNetClosing comes from the stdlib, but is not exported by the stdlib, see
// https://golang.org/issues/4373. There is a test to assert this is still a
// sound match for the behavior we're matching against.
var ErrNetClosing = errors.New("use of closed network connection")

func IsErrNetClosing(err error) bool {
	if e, ok := err.(*net.OpError); ok {
		return e.Err.Error() == ErrNetClosing.Error()
	}
	return false
}

// Server proxies all i/o to/from a serial port via another io.ReadWriter.
// Start and Stop may be pairwise called any number of times.
type Server struct {
	ServerOptions
	serial io.ReadWriteCloser
}

// ServerOptions provide options that parametrize the server's behavior.
type ServerOptions struct {
	// Logger if set to a non-nil value will receive log output for internal
	// errors that are incidental to program logic, but may be relevant for
	// diagnosis of general behaviors, such as errors in IO with the unix socket
	// clients.
	Logger *logger.Logger

	// AuxiliaryOutput is an optional serial output sink. It will be closed before
	// server.Run returns. It is dup'd for each incoming socket.
	AuxiliaryOutput *os.File

	// StartAtEnd instructs each connection to begin streaming at the end
	// of the aux file.
	StartAtEnd bool
}

// NewServer returns a new server that lives atop the given 'serial' port.
func NewServer(serial io.ReadWriteCloser, opts ServerOptions) *Server {
	s := &Server{
		ServerOptions: opts,
		serial:        serial,
	}
	return s
}

// Run begins the server and blocks until the context signals done or an error
// is encountered reading from serial. While running, all serial i/o is
// forwarded to and from the any connection accepted by the listener.
// The listener is closed by the time Run returns.
func (s *Server) Run(ctx context.Context, listener net.Listener) error {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	if s.AuxiliaryOutput == nil {
		f, err := ioutil.TempFile("", "tools-serial-aux-output")
		if err != nil {
			return err
		}
		s.AuxiliaryOutput = f
		defer os.Remove(s.AuxiliaryOutput.Name())
	}

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				// if the listener was closed, we don't care.
				if IsErrNetClosing(err) {
					return
				}
				s.errorf("serial: accept: %s", err)
				return
			}

			// Start a loop that reads whole lines from conn, and writes whole lines
			// to the serial port. This is not complete, it would be better to have a
			// proper line discipline for the serial port, however there are multiple
			// writers to the port, this being one of them. We can best-effort
			// non-conflicting writes by at least attempting to write lines as an
			// atomic unit, though this is still fallible.
			go func() {
				b := bufio.NewReader(conn)
				for {
					l, err := b.ReadString('\n')
					if err != nil {
						s.errorf("serial: conn read: %s", err)
						return
					}
					_, err = io.WriteString(s.serial, l)
					if err != nil {
						s.errorf("serial: write: %s", err)
						return
					}
				}
			}()

			go func() {
				defer conn.Close()

				f, err := os.Open(s.AuxiliaryOutput.Name())
				if err != nil {
					s.errorf("serial: %s", err)
				}
				defer f.Close()

				if s.StartAtEnd {
					_, err = f.Seek(0, io.SeekEnd)
					if err != nil {
						s.errorf("serial: seek: %s", err)
						return
					}
				}

				// keep copying until conn is closed
				buf := make([]byte, 4096)
				for {
					// files on unix always return readable, even if select'd so
					// there's no great strategy for "tailing". It's possible to relax
					// some of this to a stat loop to check for appends, and/or to use
					// filesystem watcher APIs, but in this context, this rate is both
					// easy enough on CPU and fast enough for keeping up with serial.
					select {
					case <-ctx.Done():
						return
					case <-time.After(50 * time.Millisecond):
						_, err := io.CopyBuffer(conn, f, buf)
						// io.Copy returns nil on io.EOF, which is useful here, as that's the
						// case where we read the end of the file
						if err == nil {
							continue
						}
						return
					}
				}
			}()
		}
	}()

	errs := make(chan error)
	go func() {
		buf := make([]byte, 4096)
		for {
			_, err := io.CopyBuffer(s.AuxiliaryOutput, s.serial, buf)
			if err != nil {
				errs <- err
				return
			}
		}
	}()

	var err error
	select {
	case <-ctx.Done():
		// close the serial port and wait for the copy goroutine to finish, so that
		// we are confident that auxoutput has received all of the data up to the
		// close.
		s.serial.Close()
		<-errs
	case err = <-errs:
		s.serial.Close()
		cancel()
	}

	listener.Close()
	return err
}

func (s *Server) errorf(format string, args ...interface{}) {
	if s.Logger != nil {
		s.Logger.Errorf(format, args...)
	}
}
