// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package terminal

import (
	"bytes"
	"io"
	"os"
	"syscall"
	"unsafe"
)

func isSmartTerminal(w io.Writer) bool {
	if f, ok := w.(*os.File); ok {
		if term, ok := os.LookupEnv("TERM"); ok && term == "dumb" {
			return false
		}
		var termios syscall.Termios
		_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, f.Fd(),
			ioctlGetTermios, uintptr(unsafe.Pointer(&termios)),
			0, 0, 0)
		return err == 0
	} else if _, ok := w.(*fakeSmartTerminal); ok {
		return true
	}
	return false
}

func termSize(w io.Writer) (width int, height int, ok bool) {
	if f, ok := w.(*os.File); ok {
		var winsize struct {
			wsRow, wsColumn    uint16
			wsXpixel, wsYpixel uint16
		}
		_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, f.Fd(),
			syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&winsize)),
			0, 0, 0)
		return int(winsize.wsColumn), int(winsize.wsRow), err == 0
	} else if f, ok := w.(*fakeSmartTerminal); ok {
		return f.termWidth, f.termHeight, true
	}
	return 0, 0, false
}

// stripAnsiEscapes strips ANSI control codes from a byte array in place.
func stripAnsiEscapes(input []byte) []byte {
	// read represents the remaining part of input that needs to be processed.
	read := input
	// write represents where we should be writing in input.
	// It will share the same backing store as input so that we make our modifications
	// in place.
	write := input

	// advance will copy count bytes from read to write and advance those slices
	advance := func(write, read []byte, count int) ([]byte, []byte) {
		copy(write, read[:count])
		return write[count:], read[count:]
	}

	for {
		// Find the next escape sequence
		i := bytes.IndexByte(read, 0x1b)
		// If it isn't found, or if there isn't room for <ESC>[, finish
		if i == -1 || i+1 >= len(read) {
			copy(write, read)
			break
		}

		// Not a CSI code, continue searching
		if read[i+1] != '[' {
			write, read = advance(write, read, i+1)
			continue
		}

		// Found a CSI code, advance up to the <ESC>
		write, read = advance(write, read, i)

		// Find the end of the CSI code
		i = bytes.IndexFunc(read, func(r rune) bool {
			return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z')
		})
		if i == -1 {
			// We didn't find the end of the code, just remove the rest
			i = len(read) - 1
		}

		// Strip off the end marker too
		i = i + 1

		// Skip the reader forward and reduce final length by that amount
		read = read[i:]
		input = input[:len(input)-i]
	}

	return input
}

type fakeSmartTerminal struct {
	bytes.Buffer
	termWidth, termHeight int
}
