// Copyright 2015 The Vanadium 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 main

import (
	"fmt"
	"io"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"v.io/x/ref/examples/tunnel"
	"v.io/x/ref/examples/tunnel/internal"
	"v.io/x/ref/internal/logger"
)

func runIOManager(stdin io.Reader, stdout, stderr io.Writer, stream tunnel.TunnelShellClientCall) error {
	m := ioManager{stdin: stdin, stdout: stdout, stderr: stderr, stream: stream}
	return m.run()
}

// ioManager manages the forwarding of all the data between the shell and the
// stream.
type ioManager struct {
	stdin          io.Reader
	stdout, stderr io.Writer
	stream         tunnel.TunnelShellClientCall

	// streamError receives errors coming from stream operations.
	streamError chan error
	// stdioError receives errors coming from stdio operations.
	stdioError chan error
}

func (m *ioManager) run() error {
	m.streamError = make(chan error, 1)
	m.stdioError = make(chan error, 1)

	var pendingUserInput sync.WaitGroup
	pendingUserInput.Add(1)
	var pendingStreamOutput sync.WaitGroup
	pendingStreamOutput.Add(1)

	// Forward data between the user and the remote shell.
	go func() {
		defer pendingUserInput.Done()
		// outchan is used to serialize the output to the stream.
		// chan2stream() receives data sent by handleWindowResize() and
		// user2outchan() and sends it to the stream.
		outchan := make(chan tunnel.ClientShellPacket)
		var wgStream sync.WaitGroup
		wgStream.Add(1)
		go m.chan2stream(outchan, &wgStream)

		// When the terminal window is resized, we receive a SIGWINCH. Then we
		// send the new window size to the server.
		winch := make(chan os.Signal, 1)
		signal.Notify(winch, syscall.SIGWINCH)

		var wgUser sync.WaitGroup
		wgUser.Add(2)
		go func() {
			m.user2outchan(outchan, &wgUser)
			signal.Stop(winch)
			close(winch)
		}()
		go m.handleWindowResize(winch, outchan, &wgUser)
		// When both user2outchan and handleWindowResize are done,
		// close outchan to signal chan2stream to exit.
		wgUser.Wait()
		close(outchan)
		wgStream.Wait()
	}()
	go m.stream2user(&pendingStreamOutput)
	// Block until something reports an error.
	select {
	case err := <-m.streamError:
		// When we receive an error from the stream, wait for any
		// remaining stream output to be sent to the user before
		// exiting.
		logger.Global().VI(2).Infof("run stream error: %v", err)
		pendingStreamOutput.Wait()
		return err
	case err := <-m.stdioError:
		// When we receive an error from the user, wait for any
		// remaining input from the user to be sent to the stream
		// before exiting.
		logger.Global().VI(2).Infof("run stdio error: %v", err)
		pendingUserInput.Wait()
		return err
	}
}

func (m *ioManager) sendStreamError(err error) {
	select {
	case m.streamError <- err:
	default:
	}
}

func (m *ioManager) sendStdioError(err error) {
	select {
	case m.stdioError <- err:
	default:
	}
}

// chan2stream receives ClientShellPacket from outchan and sends it to stream.
func (m *ioManager) chan2stream(outchan <-chan tunnel.ClientShellPacket, wg *sync.WaitGroup) {
	defer wg.Done()
	sender := m.stream.SendStream()
	for packet := range outchan {
		logger.Global().VI(3).Infof("chan2stream packet: %+v", packet)
		if err := sender.Send(packet); err != nil {
			logger.Global().VI(2).Infof("chan2stream: %v", err)
			m.sendStreamError(err)
		}
	}
	m.sendStreamError(io.EOF)
}

func (m *ioManager) handleWindowResize(winch <-chan os.Signal, outchan chan<- tunnel.ClientShellPacket, wg *sync.WaitGroup) {
	defer wg.Done()
	for _ = range winch {
		ws, err := internal.GetWindowSize()
		if err != nil {
			logger.Global().Infof("GetWindowSize failed: %v", err)
			continue
		}
		outchan <- tunnel.ClientShellPacketWinSize{tunnel.WindowSize{
			Rows: ws.Row,
			Cols: ws.Col,
		}}
	}
}

// user2stream reads input from stdin and sends it to the outchan.
func (m *ioManager) user2outchan(outchan chan<- tunnel.ClientShellPacket, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		buf := make([]byte, 2048)
		n, err := m.stdin.Read(buf[:])
		if err == io.EOF {
			logger.Global().VI(2).Infof("user2outchan: EOF, closing stdin")
			outchan <- tunnel.ClientShellPacketEndOfFile{}
			return
		}
		if err != nil {
			logger.Global().VI(2).Infof("user2outchan: %v", err)
			m.sendStdioError(err)
			return
		}
		outchan <- tunnel.ClientShellPacketStdin{buf[:n]}
	}
}

// stream2user reads data from the stream and sends it to either stdout or stderr.
func (m *ioManager) stream2user(wg *sync.WaitGroup) {
	defer wg.Done()
	rStream := m.stream.RecvStream()
	for rStream.Advance() {
		packet := rStream.Value()
		logger.Global().VI(3).Infof("stream2user packet: %+v", packet)

		switch v := packet.(type) {
		case tunnel.ServerShellPacketStdout:
			if n, err := m.stdout.Write(v.Value); n != len(v.Value) || err != nil {
				m.sendStdioError(fmt.Errorf("stdout.Write returned (%d, %v) want (%d, nil)", n, err, len(v.Value)))
				return
			}
		case tunnel.ServerShellPacketStderr:
			if n, err := m.stderr.Write(v.Value); n != len(v.Value) || err != nil {
				m.sendStdioError(fmt.Errorf("stderr.Write returned (%d, %v) want (%d, nil)", n, err, len(v.Value)))
				return
			}
		default:
			logger.Global().Infof("unexpected message type: %T", packet)
		}
	}
	err := rStream.Err()
	if err == nil {
		err = io.EOF
	}
	logger.Global().VI(2).Infof("stream2user: %v", err)
	m.sendStreamError(err)
}
