package door

import (
	"log"
	"strings"
	"syscall"
)

// https://go101.org/article/channel-closing.html

func Writer(d *Door) {
	var handle int = d.Config.Comm_handle
	log.Println("Writer")
	defer d.wg.Done()
	var Closed bool = false

	for {
		select {
		case output, ok := <-d.writerChannel:
			if !ok {
				log.Println("closeChannel")

				d.writerMutex.Lock()
				if !d.WriterClosed {
					// Safe from data races, writerChannel unbuffered
					d.WriterClosed = true
				}
				d.writerMutex.Unlock()
				log.Println("~Writer")
				return

			} else {
				// log.Println("output")
				/* Handle cases where we're updating a portion of the screen.
				When we SavePos, also save/restore the last color set.
				*/
				if output == "" {
					Closed = true
					continue
				}

				if Closed {
					log.Println("ignoring write output.")
					continue
				}

				if strings.HasSuffix(output, RestorePos) {
					output += Color(d.LastColor...)

				} else {
					d.UpdateLastColor(output, &d.LastColor)
				}
				// log.Println("write output")
				buffer := []byte(output)

				n, err := syscall.Write(handle, buffer)
				if (err != nil) || (n != len(buffer)) {
					log.Println("closeChannel")
					Closed = true
					d.writerMutex.Lock()
					if !d.WriterClosed {
						d.WriterClosed = true
						// close(d.writerChannel)
					}
					d.writerMutex.Unlock()
				}

			}
		}
	}
}