// Copyright 2023 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Package progressbar provides functions for drawing Unicode progress bars to
// the terminal
package progressbar

import (
	"bytes"
	"fmt"
	"io"
	"math"
	"strings"
	"time"

	"dawn.googlesource.com/dawn/tools/src/term"
)

// Defaults for the Config
const (
	DefaultRefreshRate = time.Millisecond * 100
	DefaultWidth       = 50
	DefaultANSIColors  = true
)

// Config holds configuration options for a ProgressBar
type Config struct {
	RefreshRate time.Duration
	Width       int
	ANSIColors  bool
}

// Color is an enumerator of colors
type Color int

// Color enumerators
const (
	White Color = iota
	Red
	Green
	Yellow
	Blue
	Magenta
	Cyan
)

// Segment describes a single segment of the ProgressBar
type Segment struct {
	Count       int
	Color       Color
	Transparent bool
	Bold        bool
}

// Status holds the updated data of the ProgressBar
type Status struct {
	Total    int
	Segments []Segment
}

// ProgressBar is an interface for progress bars.
type ProgressBar interface {
	// Update updates the ProgressBar with the given status
	Update(s Status)
	// Stop stops drawing the progress bar.
	// Once called, the ProgressBar must not be used.
	Stop()
}

type Build func(out io.Writer, cfg *Config) ProgressBar

// New returns a new ProgressBar that streams output to out.
// Selects between realProgressBar and StubProgressBar automatically depending
// on if the output will be displayed in the terminal correctly.
// Call ProgressBar.Stop() once finished.
func New(out io.Writer, cfg *Config) ProgressBar {
	if !term.CanUseAnsiEscapeSequences() {
		return NewStubProgressBar(out, cfg)
	}

	return newRealProgressBar(out, cfg)
}

// NewRealProgressBar constructs and returns a realProgressBar.
// Does not check if the terminal supports the needed escape characters, which
// is why it is not exposed outside the package, use New() instead.
func newRealProgressBar(out io.Writer, cfg *Config) ProgressBar {
	p := &realProgressBar{out: out, c: make(chan Status, 64)}
	if cfg != nil {
		p.Config = *cfg
	} else {
		p.ANSIColors = DefaultANSIColors
	}
	if p.RefreshRate == 0 {
		p.RefreshRate = DefaultRefreshRate
	}
	if p.Width == 0 {
		p.Width = DefaultWidth
	}
	go func() {
		var status *Status
		t := time.NewTicker(p.RefreshRate)
		defer t.Stop()
		for frame := 0; ; frame++ {
			select {
			case s, ok := <-p.c:
				if !ok {
					return
				}
				status = &s
			case <-t.C:
				if status != nil {
					status.Draw(out, p.Width, p.ANSIColors, frame)
				}
			}
		}
	}()
	return p
}

// NewStubProgressBar returns a new StubProgressBar, used in tests to guarantee
// the type of ProgressBar returned.
// Note: In production code, use New() instead.
func NewStubProgressBar(_ io.Writer, _ *Config) ProgressBar {
	return &StubProgressBar{}
}

// StubProgressBar is a ProgressBar that does nothing, used in environments that
// don't support the control characters needed or when testing to avoid spamming
// output.
type StubProgressBar struct{}

func (p *StubProgressBar) Update(s Status) {}

func (p *StubProgressBar) Stop() {}

// realProgressBar writes out a string with an ANSI-colored progress bar,
// providing realtime information about the status of the CTS run.
// Note: Does not work if !isatty or if running on windows.
type realProgressBar struct {
	Config
	out io.Writer
	c   chan Status
}

func (p *realProgressBar) Update(s Status) {
	p.c <- s
}

func (p *realProgressBar) Stop() {
	close(p.c)
}

// Draw draws the ProgressBar status to out
func (s Status) Draw(out io.Writer, width int, ansiColors bool, animFrame int) {
	// ANSI escape sequences
	const (
		escape       = "\u001B["
		positionLeft = escape + "0G"
		ansiReset    = escape + "0m"

		bold = escape + "1m"

		red     = escape + "31m"
		green   = escape + "32m"
		yellow  = escape + "33m"
		blue    = escape + "34m"
		magenta = escape + "35m"
		cyan    = escape + "36m"
		white   = escape + "37m"
	)

	animSymbols := []rune{'⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'}
	blockSymbols := []rune{'▏', '▎', '▍', '▌', '▋', '▊', '▉'}

	numBlocksPrinted := 0

	buf := &bytes.Buffer{}
	fmt.Fprint(buf, "  ", string(animSymbols[animFrame%len(animSymbols)]), " [")

	numFinished := 0
	for _, seg := range s.Segments {
		if ansiColors {
			switch seg.Color {
			case Red:
				buf.WriteString(red)
			case Green:
				buf.WriteString(green)
			case Yellow:
				buf.WriteString(yellow)
			case Blue:
				buf.WriteString(blue)
			case Magenta:
				buf.WriteString(magenta)
			case Cyan:
				buf.WriteString(cyan)
			default:
				buf.WriteString(white)
			}
			if seg.Bold {
				buf.WriteString(bold)
			}
		}

		numFinished += seg.Count
		statusFrac := float64(seg.Count) / float64(s.Total)
		fNumBlocks := float64(width) * statusFrac
		numBlocks := int(math.Ceil(fNumBlocks))
		if seg.Transparent {
			if numBlocks > 0 {
				fmt.Fprint(buf, strings.Repeat(string("░"), numBlocks))
			}
		} else {
			if numBlocks > 1 {
				fmt.Fprint(buf, strings.Repeat(string("▉"), numBlocks-1))
			}
			if numBlocks > 0 {
				frac := fNumBlocks - float64(numBlocks-1)
				symbol := blockSymbols[int(math.Round(frac*float64(len(blockSymbols)-1)))]
				fmt.Fprint(buf, string(symbol))
			}
		}
		numBlocksPrinted += numBlocks
	}

	if width > numBlocksPrinted {
		fmt.Fprint(buf, strings.Repeat(string(" "), width-numBlocksPrinted))
	}
	fmt.Fprint(buf, ansiReset)
	fmt.Fprint(buf, "] ", percentage(numFinished, s.Total))

	if ansiColors {
		// move cursor to start of line so the bar is overridden next print
		fmt.Fprint(buf, positionLeft)
	} else {
		// cannot move cursor, so newline
		fmt.Fprintln(buf)
	}

	out.Write(buf.Bytes())
}

// percentage returns the percentage of n out of total as a string
func percentage(n, total int) string {
	if total == 0 {
		return "-"
	}
	f := float64(n) / float64(total)
	return fmt.Sprintf("%.1f%c", f*100.0, '%')
}
